1
0
Fork 0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-06-08 00:07:34 +09:00

Char/Misc/IIO pull request for 6.16-rc1

Here is the big char/misc/iio and other small driver subsystem pull
 request for 6.16-rc1.
 
 Overall, a lot of individual changes, but nothing major, just the normal
 constant forward progress of new device support and cleanups to existing
 subsystems.  Highlights in here are:
   - Large IIO driver updates and additions and device tree changes
   - Android binder bugfixes and logfile fixes
   - mhi driver updates
   - comedi driver updates
   - counter driver updates and additions
   - coresight driver updates and additions
   - echo driver removal as there are no in-kernel users of it
   - nvmem driver updates
   - spmi driver updates
   - new amd-sbi driver "subsystem" and drivers added
   - rust miscdriver binding documentation fix
   - other small driver fixes and updates (uio, w1, acrn, hpet, xillybus,
     cardreader drivers, fastrpc and others.)
 
 All of these have been in linux-next for quite a while with no reported
 problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaEKg5Q8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykUyACgmAzrzKMoQUwwhQ6ed2l7tHdrlOcAoIORI1/x
 pNqQdrE1EbmAAyl47IN4
 =ts6J
 -----END PGP SIGNATURE-----

Merge tag 'char-misc-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char / misc / iio driver updates from Greg KH:
 "Here is the big char/misc/iio and other small driver subsystem pull
  request for 6.16-rc1.

  Overall, a lot of individual changes, but nothing major, just the
  normal constant forward progress of new device support and cleanups to
  existing subsystems. Highlights in here are:

   - Large IIO driver updates and additions and device tree changes

   - Android binder bugfixes and logfile fixes

   - mhi driver updates

   - comedi driver updates

   - counter driver updates and additions

   - coresight driver updates and additions

   - echo driver removal as there are no in-kernel users of it

   - nvmem driver updates

   - spmi driver updates

   - new amd-sbi driver "subsystem" and drivers added

   - rust miscdriver binding documentation fix

   - other small driver fixes and updates (uio, w1, acrn, hpet,
     xillybus, cardreader drivers, fastrpc and others)

  All of these have been in linux-next for quite a while with no
  reported problems"

* tag 'char-misc-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (390 commits)
  binder: fix yet another UAF in binder_devices
  counter: microchip-tcb-capture: Add watch validation support
  dt-bindings: iio: adc: Add ROHM BD79100G
  iio: adc: add support for Nuvoton NCT7201
  dt-bindings: iio: adc: add NCT7201 ADCs
  iio: chemical: Add driver for SEN0322
  dt-bindings: trivial-devices: Document SEN0322
  iio: adc: ad7768-1: reorganize driver headers
  iio: bmp280: zero-init buffer
  iio: ssp_sensors: optimalize -> optimize
  HID: sensor-hub: Fix typo and improve documentation
  iio: admv1013: replace redundant ternary operator with just len
  iio: chemical: mhz19b: Fix error code in probe()
  iio: adc: at91-sama5d2: use IIO_DECLARE_BUFFER_WITH_TS
  iio: accel: sca3300: use IIO_DECLARE_BUFFER_WITH_TS
  iio: adc: ad7380: use IIO_DECLARE_DMA_BUFFER_WITH_TS
  iio: adc: ad4695: rename AD4695_MAX_VIN_CHANNELS
  iio: adc: ad4695: use IIO_DECLARE_DMA_BUFFER_WITH_TS
  iio: introduce IIO_DECLARE_BUFFER_WITH_TS macros
  iio: make IIO_DMA_MINALIGN minimum of 8 bytes
  ...
This commit is contained in:
Linus Torvalds 2025-06-06 11:50:47 -07:00
commit c26f4fbd58
601 changed files with 12372 additions and 6148 deletions

View file

@ -94,6 +94,7 @@ Description:
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_sampling_frequency
What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency
What: /sys/bus/iio/devices/iio:deviceX/events/sampling_frequency
What: /sys/bus/iio/devices/triggerX/sampling_frequency
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
@ -740,7 +741,9 @@ Description:
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
7.7kohm_to_gnd: connected to ground via a 7.7kOhm resistor,
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
32kohm_to_gnd: connected to ground via a 32kOhm resistor,
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
100kohm_to_gnd: connected to ground via an 100kOhm resistor,

View file

@ -17,7 +17,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
Date: January 2021
KernelVersion: 5.12
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns the first MAC address in a block
of sequential MAC addresses assigned to the board
that is managed by the Intel MAX10 BMC. It is stored in
@ -28,7 +28,7 @@ Description: Read only. Returns the first MAC address in a block
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
Date: January 2021
KernelVersion: 5.12
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns the number of sequential MAC
addresses assigned to the board managed by the Intel
MAX10 BMC. This value is stored in FLASH and is mirrored

View file

@ -1,7 +1,7 @@
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns the root entry hash for the static
region if one is programmed, else it returns the
string: "hash not programmed". This file is only
@ -11,7 +11,7 @@ Description: Read only. Returns the root entry hash for the static
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns the root entry hash for the partial
reconfiguration region if one is programmed, else it
returns the string: "hash not programmed". This file
@ -21,7 +21,7 @@ Description: Read only. Returns the root entry hash for the partial
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns the root entry hash for the BMC image
if one is programmed, else it returns the string:
"hash not programmed". This file is only visible if the
@ -31,7 +31,7 @@ Description: Read only. Returns the root entry hash for the BMC image
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the static region. The standard bitmap
list format is used (e.g. "1,2-6,9").
@ -39,7 +39,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the partial reconfiguration region. The
standard bitmap list format is used (e.g. "1,2-6,9").
@ -47,7 +47,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the BMC. The standard bitmap list format
is used (e.g. "1,2-6,9").
@ -55,7 +55,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/flash_count
Date: Sep 2022
KernelVersion: 5.20
Contact: Peter Colberg <peter.colberg@altera.com>
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
Description: Read only. Returns number of times the secure update
staging area has been flashed.
Format: "%u".

View file

@ -30,6 +30,19 @@ properties:
power-domains:
maxItems: 1
clocks:
minItems: 1
maxItems: 3
clock-names:
oneOf:
- items:
- enum: [apb_pclk, atclk]
- items: # Zynq-700
- const: apb_pclk
- const: dbg_trc
- const: dbg_apb
in-ports:
$ref: /schemas/graph.yaml#/properties/ports
additionalProperties: false

View file

@ -25,6 +25,7 @@ description: |
* https://www.analog.com/en/products/ad7386-4.html
* https://www.analog.com/en/products/ad7387-4.html
* https://www.analog.com/en/products/ad7388-4.html
* https://www.analog.com/en/products/ad7389-4.html
* https://www.analog.com/en/products/adaq4370-4.html
* https://www.analog.com/en/products/adaq4380-4.html
* https://www.analog.com/en/products/adaq4381-4.html
@ -49,6 +50,7 @@ properties:
- adi,ad7386-4
- adi,ad7387-4
- adi,ad7388-4
- adi,ad7389-4
- adi,adaq4370-4
- adi,adaq4380-4
- adi,adaq4381-4
@ -213,6 +215,15 @@ allOf:
properties:
refin-supply: false
# adi,ad7389-4 is internal reference only
- if:
properties:
compatible:
const: adi,ad7389-4
then:
properties:
refio-supply: false
# adaq devices need more supplies and using channel to declare gain property
# only applies to adaq devices
- if:

View file

@ -17,7 +17,9 @@ description: |
properties:
compatible:
enum:
oneOf:
- items:
- enum:
- adi,ad7091
- adi,ad7091r
- adi,ad7273
@ -46,6 +48,9 @@ properties:
- ti,ads7867
- ti,ads7868
- lltc,ltc2314-14
- items:
- const: rohm,bu79100g
- const: ti,ads7866
reg:
maxItems: 1

View file

@ -45,6 +45,14 @@ properties:
"#size-cells":
const: 0
'#trigger-source-cells':
description: |
Cell indicates the output signal: 0 = BUSY, 1 = FIRSTDATA.
For convenience, macros for these values are available in
dt-bindings/iio/adc/adi,ad7606.h.
const: 1
# According to the datasheet, "Data is clocked in from SDI on the falling
# edge of SCLK, while data is clocked out on DOUTA on the rising edge of
# SCLK". Also, even if not stated textually in the datasheet, it is made

View file

@ -23,6 +23,7 @@ properties:
- amlogic,meson8m2-saradc
- amlogic,meson-gxbb-saradc
- amlogic,meson-gxl-saradc
- amlogic,meson-gxlx-saradc
- amlogic,meson-gxm-saradc
- amlogic,meson-axg-saradc
- amlogic,meson-g12a-saradc

View file

@ -34,6 +34,7 @@ properties:
- const: mediatek,mt2701-auxadc
- items:
- enum:
- mediatek,mt6893-auxadc
- mediatek,mt8183-auxadc
- mediatek,mt8186-auxadc
- mediatek,mt8188-auxadc

View file

@ -32,6 +32,9 @@ properties:
spi-max-frequency:
maximum: 20000000
reset-gpios:
maxItems: 1
clocks:
description: |
Phandle and clock identifier for external sampling clock.
@ -71,6 +74,7 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
@ -80,6 +84,7 @@ examples:
reg = <0>;
interrupt-parent = <&gpio5>;
interrupts = <15 2>;
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
spi-max-frequency = <20000000>;
microchip,device-addr = <0>;
vref-supply = <&vref_reg>;

View file

@ -0,0 +1,70 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/nuvoton,nct7201.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton nct7201 and similar ADCs
maintainers:
- Eason Yang <j2anfernee@gmail.com>
description: |
The NCT7201/NCT7202 is a Nuvoton Hardware Monitor IC, contains up to 12
voltage monitoring channels, with SMBus interface, and up to 4 sets SMBus
address selection by ADDR connection. It also provides ALERT# signal for
event notification and reset input RSTIN# to recover it from a fault
condition.
NCT7201 contains 8 voltage monitor inputs (VIN1~VIN8).
NCT7202 contains 12 voltage monitor inputs (VIN1~VIN12).
properties:
compatible:
enum:
- nuvoton,nct7201
- nuvoton,nct7202
reg:
maxItems: 1
vdd-supply:
description:
A 3.3V to supply that powers the chip.
vref-supply:
description:
The regulator supply for the ADC reference voltage.
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
adc@1d {
compatible = "nuvoton,nct7202";
reg = <0x1d>;
vdd-supply = <&vdd>;
vref-supply = <&vref>;
interrupt-parent = <&gpio3>;
interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
};
};
...

View file

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79104.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM Semiconductor BD79104 ADC
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
12 bit SPI ADC with 8 channels.
properties:
compatible:
const: rohm,bd79104
reg:
maxItems: 1
vdd-supply: true
iovdd-supply: true
# The component data-sheet says the frequency is 20M. I, however, found
# that the ROHM evaluation board BD79104FV-EVK-001 had problems with 20M.
# I have successfully used it with 4M. My _assumption_ is that this is not
# the limitation of the component itself, but a limitation of the EVK.
spi-max-frequency:
maximum: 20000000
"#io-channel-cells":
const: 1
spi-cpha: true
spi-cpol: true
required:
- compatible
- reg
- vdd-supply
- iovdd-supply
- spi-cpha
- spi-cpol
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "rohm,bd79104";
reg = <0>;
vdd-supply = <&vdd_supply>;
iovdd-supply = <&iovdd_supply>;
spi-max-frequency = <4000000>;
spi-cpha;
spi-cpol;
#io-channel-cells = <1>;
};
};
...

View file

@ -0,0 +1,114 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79124.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BD79124 ADC/GPO
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
an automatic measurement mode, with an alarm interrupt for out-of-window
measurements. ADC input pins can be also configured as general purpose
outputs.
properties:
compatible:
const: rohm,bd79124
reg:
description:
I2C slave address.
maxItems: 1
interrupts:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 1
description:
The pin number.
vdd-supply: true
iovdd-supply: true
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^channel@[0-7]+$":
type: object
$ref: /schemas/iio/adc/adc.yaml#
description: Represents ADC channel.
properties:
reg:
description: AIN pin number
minimum: 0
maximum: 7
required:
- reg
additionalProperties: false
required:
- compatible
- reg
- iovdd-supply
- vdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
adc: adc@10 {
compatible = "rohm,bd79124";
reg = <0x10>;
interrupt-parent = <&gpio1>;
interrupts = <29 8>;
vdd-supply = <&dummyreg>;
iovdd-supply = <&dummyreg>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
};
channel@1 {
reg = <1>;
};
channel@2 {
reg = <2>;
};
channel@3 {
reg = <3>;
};
channel@4 {
reg = <4>;
};
channel@5 {
reg = <5>;
};
channel@6 {
reg = <6>;
};
};
};

View file

@ -0,0 +1,33 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/chemical/winsen,mhz19b.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MHZ19B CO2 sensor
maintainers:
- Gyeyoung Baek <gye976@gmail.com>
properties:
compatible:
const: winsen,mhz19b
vin-supply:
description: Regulator that provides power to the sensor
required:
- compatible
- vin-supply
additionalProperties: false
examples:
- |
serial {
co2-sensor {
compatible = "winsen,mhz19b";
vin-supply = <&vdd>;
};
};
...

View file

@ -0,0 +1,100 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/adi,ad3530r.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD3530R and Similar DACs
maintainers:
- Kim Seer Paller <kimseer.paller@analog.com>
description: |
The AD3530/AD3530R (8-channel) and AD3531/AD3531R (4-channel) are low-power,
16-bit, buffered voltage output digital-to-analog converters (DACs) with
software-programmable gain controls, providing full-scale output spans of 2.5V
or 5V for reference voltages of 2.5V. These devices operate from a single 2.7V
to 5.5V supply and are guaranteed monotonic by design. The "R" variants
include a 2.5V, 5ppm/°C internal reference, which is disabled by default.
Datasheet can be found here:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3530_ad530r.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3531-ad3531r.pdf
properties:
compatible:
enum:
- adi,ad3530
- adi,ad3530r
- adi,ad3531
- adi,ad3531r
reg:
maxItems: 1
spi-max-frequency:
maximum: 50000000
vdd-supply:
description: Power Supply Input.
iovdd-supply:
description: Digital Power Supply Input.
io-channels:
description:
ADC channel used to monitor internal die temperature, output voltages, and
current of a selected channel via the MUXOUT pin.
maxItems: 1
ref-supply:
description:
Reference Input/Output. The voltage at the REF pin sets the full-scale
range of all channels. If not provided the internal reference is used and
also provided on the VREF pin.
reset-gpios:
description:
Active low signal that is falling edge sensitive. When it is deasserted,
the digital core initialization is performed and all DAC registers except
the Interface Configuration A register are reset to their default values.
maxItems: 1
ldac-gpios:
description:
LDAC pin to be used as a hardware trigger to update the DAC channels. If
not present, the DAC channels are updated by Software LDAC.
maxItems: 1
adi,range-double:
description:
Configure the output range for all channels. If the property is present,
the output will range from 0V to 2Vref. If the property is not present,
the output will range from 0V to Vref.
type: boolean
required:
- compatible
- reg
- vdd-supply
- iovdd-supply
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
dac@0 {
compatible = "adi,ad3530r";
reg = <0>;
spi-max-frequency = <1000000>;
vdd-supply = <&vdd>;
iovdd-supply = <&iovdd>;
};
};
...

View file

@ -217,7 +217,7 @@ required:
- reg
- spi-max-frequency
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -27,6 +27,8 @@ properties:
vdrive-supply: true
vrefin-supply: true
reset-gpios:
maxItems: 1

View file

@ -144,7 +144,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -124,7 +124,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -64,7 +64,7 @@ required:
- reg
- vdd-supply
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -5,19 +5,26 @@
$id: http://devicetree.org/schemas/iio/dac/rohm,bd79703.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BD79703 DAC device driver
title: ROHM BD79700, BD79701, BD79702 and BD79703 DACs
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
The ROHM BD79703 is a 6 channel, 8-bit DAC.
Datasheet can be found here:
The ROHM BD7970[0,1,2,3] are 8-bit DACs. The BD79700 has 2 channels,
BD79701 3 channels, BD79702 4 channels and BD79703 has 6 channels.
Datasheets for BD79702 and BD79703 can be found from
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79702fv-lb_bd79703fv-lb-e.pdf
and for the BD79700 and the BD79701 from
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79700fvm-lb_bd79701fvm-lb-e.pdf
properties:
compatible:
const: rohm,bd79703
enum:
- rohm,bd79700
- rohm,bd79701
- rohm,bd79702
- rohm,bd79703
reg:
maxItems: 1
@ -27,23 +34,35 @@ properties:
vfs-supply:
description:
The regulator to use as a full scale voltage. The voltage should be between 2.7V .. VCC
The regulator to use as a full scale voltage. The voltage should be
between 2.7V .. VCC. Not present on BD79700 and BD79701.
vcc-supply:
description:
The regulator supplying the operating voltage. Should be between 2.7V ... 5.5V
The regulator supplying the operating voltage. Should be between
2.7V ... 5.5V. Is used also as a Vfs on BD79700 and BD79701.
required:
- compatible
- reg
- spi-max-frequency
- vfs-supply
- vcc-supply
if:
properties:
compatible:
contains:
enum:
- rohm,bd79702
- rohm,bd79703
then:
required:
- vfs-supply
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -44,6 +44,24 @@ properties:
'#clock-cells':
const: 0
adi,lpf-margin-mhz:
description:
Sets the minimum distance between the fundamental frequency of `rf_in`
and the corner frequency of the low-pass, output filter when operated in
'auto' mode. The selected low-pass corner frequency will be greater than,
or equal to, `rf_in` + `lpf-margin-hz`. If not setting is found that
satisfies this relationship the filter will be put into 'bypass'.
default: 0
adi,hpf-margin-mhz:
description:
Sets the minimum distance between the fundamental frequency of `rf_in`
and the corner frequency of the high-pass, input filter when operated in
'auto' mode. The selected high-pass corner frequency will be less than,
or equal to, `rf_in` - `hpf-margin-hz`. If not setting is found that
satisfies this relationship the filter will be put into 'bypass'.
default: 0
required:
- compatible
- reg
@ -61,6 +79,8 @@ examples:
spi-max-frequency = <10000000>;
clocks = <&admv8818_rfin>;
clock-names = "rf_in";
adi,lpf-margin-mhz = <300>;
adi,hpf-margin-mhz = <300>;
};
};
...

View file

@ -53,7 +53,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -39,7 +39,16 @@ properties:
maxItems: 1
interrupts:
maxItems: 1
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
maxItems: 2
items:
enum:
- INT1
- INT2
drive-open-drain:
type: boolean
@ -76,6 +85,7 @@ examples:
reg = <0x68>;
interrupt-parent = <&gpio2>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
interrupt-names = "INT1";
vdd-supply = <&vdd>;
vddio-supply = <&vddio>;
};
@ -95,6 +105,7 @@ examples:
spi-cpol;
interrupt-parent = <&gpio1>;
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
interrupt-names = "INT1";
vdd-supply = <&vdd>;
vddio-supply = <&vddio>;
};

View file

@ -24,6 +24,10 @@ properties:
reg:
maxItems: 1
reset-gpios:
description: GPIO connected to the DVI reset pin (active low)
maxItems: 1
required:
- compatible
- reg
@ -32,6 +36,7 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
@ -39,6 +44,7 @@ examples:
light-sensor@23 {
compatible = "rohm,bh1750";
reg = <0x23>;
reset-gpios = <&gpio2 17 GPIO_ACTIVE_LOW>;
};
};

View file

@ -102,7 +102,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml
additionalProperties: false
unevaluatedProperties: false
dependentSchemas:
honeywell,pmin-pascal:

View file

@ -115,7 +115,7 @@ allOf:
honeywell,pmin-pascal: false
honeywell,pmax-pascal: false
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -86,13 +86,13 @@ examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
snoc: interconnect@580000 {
interconnect@580000 {
compatible = "qcom,msm8953-snoc";
reg = <0x580000 0x16080>;
#interconnect-cells = <2>;
snoc_mm: interconnect-snoc {
interconnect-snoc {
compatible = "qcom,msm8953-snoc-mm";
#interconnect-cells = <2>;

View file

@ -52,7 +52,7 @@ examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
bimc: interconnect@fc380000 {
interconnect@fc380000 {
reg = <0xfc380000 0x6a000>;
compatible = "qcom,msm8974-bimc";
#interconnect-cells = <1>;

View file

@ -28,6 +28,7 @@ properties:
- const: qcom,osm-l3
- items:
- enum:
- qcom,sa8775p-epss-l3
- qcom,sc7280-epss-l3
- qcom,sc8280xp-epss-l3
- qcom,sm6375-cpucp-l3

View file

@ -43,7 +43,7 @@ examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
bimc: interconnect@400000 {
interconnect@400000 {
compatible = "qcom,msm8916-bimc";
reg = <0x00400000 0x62000>;
#interconnect-cells = <1>;

View file

@ -129,14 +129,14 @@ examples:
- |
#include <dt-bindings/interconnect/qcom,sdm845.h>
mem_noc: interconnect@1380000 {
interconnect@1380000 {
compatible = "qcom,sdm845-mem-noc";
reg = <0x01380000 0x27200>;
#interconnect-cells = <1>;
qcom,bcm-voters = <&apps_bcm_voter>;
};
mmss_noc: interconnect@1740000 {
interconnect@1740000 {
compatible = "qcom,sdm845-mmss-noc";
reg = <0x01740000 0x1c1000>;
#interconnect-cells = <1>;

View file

@ -25,6 +25,10 @@ properties:
description:
List of gpios used to control the multiplexer, least significant bit first.
mux-supply:
description:
Regulator to power on the multiplexer.
'#mux-control-cells':
enum: [ 0, 1 ]

View file

@ -0,0 +1,54 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvmem/apple,spmi-nvmem.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple SPMI NVMEM
description: Exports a series of SPMI registers as NVMEM cells
maintainers:
- Sasha Finkelstein <fnkl.kernel@gmail.com>
allOf:
- $ref: nvmem.yaml#
properties:
compatible:
items:
- enum:
- apple,maverick-pmic
- apple,sera-pmic
- apple,stowe-pmic
- const: apple,spmi-nvmem
reg:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/spmi/spmi.h>
pmic@f {
compatible = "apple,maverick-pmic", "apple,spmi-nvmem";
reg = <0xf SPMI_USID>;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
boot_stage: boot-stage@6001 {
reg = <0x6001 0x1>;
};
};
};
...

View file

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple SPMI controller
maintainers:
- Sasha Finkelstein <fnkl.kernel@gmail.com>
description: A SPMI controller present on most Apple SoCs
allOf:
- $ref: spmi.yaml#
properties:
compatible:
items:
- enum:
- apple,t8103-spmi
- apple,t6000-spmi
- apple,t8112-spmi
- const: apple,spmi
reg:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/spmi/spmi.h>
spmi@920a1300 {
compatible = "apple,t6000-spmi", "apple,spmi";
reg = <0x920a1300 0x100>;
#address-cells = <2>;
#size-cells = <0>;
pmic@f {
reg = <0xf SPMI_USID>;
/* PMIC-specific properties */
};
};

View file

@ -85,6 +85,8 @@ properties:
- devantech,srf08
# Devantech SRF10 ultrasonic ranger
- devantech,srf10
# DFRobot SEN0322 oxygen sensor
- dfrobot,sen0322
# DH electronics GmbH on-board CPLD trivial SPI device
- dh,dhcom-board
# DA9053: flexible system level PMIC with multicore support

View file

@ -1705,6 +1705,8 @@ patternProperties:
description: Wingtech Technology Co., Ltd.
"^winlink,.*":
description: WinLink Co., Ltd
"^winsen,.*":
description: Winsen Corp.
"^winstar,.*":
description: Winstar Display Corp.
"^wirelesstag,.*":

View file

@ -59,10 +59,10 @@ For example, a simple nvram case::
devm_nvmem_register(&config);
}
Users of board files can define and register nvmem cells using the
nvmem_cell_table struct::
Device drivers can define and register an nvmem cell using the nvmem_cell_info
struct::
static struct nvmem_cell_info foo_nvmem_cells[] = {
static const struct nvmem_cell_info foo_nvmem_cell = {
{
.name = "macaddr",
.offset = 0x7f00,
@ -70,13 +70,7 @@ nvmem_cell_table struct::
}
};
static struct nvmem_cell_table foo_nvmem_cell_table = {
.nvmem_name = "i2c-eeprom",
.cells = foo_nvmem_cells,
.ncells = ARRAY_SIZE(foo_nvmem_cells),
};
nvmem_add_cell_table(&foo_nvmem_cell_table);
int nvmem_add_one_cell(nvmem, &foo_nvmem_cell);
Additionally it is possible to create nvmem cell lookup entries and register
them with the nvmem framework from machine code as shown in the example below::

View file

@ -0,0 +1,72 @@
.. SPDX-License-Identifier: GPL-2.0-only
==============
AD3552R driver
==============
Device driver for Analog Devices Inc. AD35XXR series of DACs. The module name
is ``ad3552r``.
With the same module name, two different driver variants are available, the
``generic spi`` variant, to be used with any classic SPI controllers, and the
``hs`` (high speed) variant, for an ADI ``axi-dac`` (IP core) based controller
that allows to reach the maximum sample rate supported from the DACs, using the
DMA transfer and all the SPI lines available (D/QDSPI)..
The high speed driver variant is intended to be used with the ``adi-axi-dac``
backend support enabled, that is enabled by default when the driver is selected.
Supported devices
=================
* `AD3541R <https://www.analog.com/en/products/ad3541r.html>`_
* `AD3542R <https://www.analog.com/en/products/ad3542r.html>`_
* `AD3551R <https://www.analog.com/en/products/ad3551r.html>`_
* `AD3552R <https://www.analog.com/en/products/ad3552r.html>`_
Wiring connections
==================
Generic SPI
-----------
Use the classic SPI S_CLK/CS/SDO/SDI connection.
High speed (using axi-dac backend)
----------------------------------
::
.-----------------. .-------.
| |--- D/QSPI -----| |
| DAC IP CORE |--- SPI S_CLK --| DAC |
| |--- SPI CS -----| |
| |--- LDAC -------| |
| |--- RESET ------| |
|_________________| |_______|
High speed features
===================
Device attributes
-----------------
The following table shows the ad35xxr related device debug files, found in the
specific debugfs path ``/sys/kernel/debug/iio/iio:deviceX``.
+-----------------------+------------------------------------------------------+
| Debugfs device files | Description |
+-----------------------+------------------------------------------------------+
| data_source | The used data source, as |
| | ``normal``, ``ramp-16bit``, etc. |
+-----------------------+------------------------------------------------------+
| data_source_available | The available data sources. |
+-----------------------+------------------------------------------------------+
Usage examples
--------------
. code-block:: bash
root:/sys/bus/iio/devices/iio:device0# cat data_source
normal
root:/sys/bus/iio/devices/iio:device0# echo -n ramp-16bit > data_source
root:/sys/bus/iio/devices/iio:device0# cat data_source
ramp-16bit

View file

@ -4,7 +4,7 @@
AD4000 driver
=============
Device driver for Analog Devices Inc. AD4000 series of ADCs.
Device driver for Analog Devices Inc. AD4000 series of ADCs and similar devices.
Supported devices
=================
@ -25,6 +25,21 @@ Supported devices
* `AD4022 <https://www.analog.com/AD4022>`_
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
* `ADAQ4003 <https://www.analog.com/ADAQ4003>`_
* `AD7685 <https://www.analog.com/AD7685>`_
* `AD7686 <https://www.analog.com/AD7686>`_
* `AD7687 <https://www.analog.com/AD7687>`_
* `AD7688 <https://www.analog.com/AD7688>`_
* `AD7690 <https://www.analog.com/AD7690>`_
* `AD7691 <https://www.analog.com/AD7691>`_
* `AD7693 <https://www.analog.com/AD7693>`_
* `AD7942 <https://www.analog.com/AD7942>`_
* `AD7946 <https://www.analog.com/AD7946>`_
* `AD7980 <https://www.analog.com/AD7980>`_
* `AD7982 <https://www.analog.com/AD7982>`_
* `AD7983 <https://www.analog.com/AD7983>`_
* `AD7984 <https://www.analog.com/AD7984>`_
* `AD7988-1 <https://www.analog.com/AD7988-1>`_
* `AD7988-5 <https://www.analog.com/AD7988-5>`_
Wiring connections
------------------
@ -129,3 +144,77 @@ Set ``adi,sdi-pin`` to ``"cs"`` to select this mode.
^ | |
+--------------------| SCLK |
+-------------+
IIO Device characteristics
==========================
The AD4000 series driver supports differential and pseudo-differential ADCs.
The span compression feature available in AD4000 series devices can be
enabled/disabled by changing the ``_scale_available`` attribute of the voltage
channel. Note that span compression configuration requires writing to AD4000
configuration register, which is only possible when the ADC is wired in 3-wire
turbo mode, and the SPI controller is ``SPI_MOSI_IDLE_HIGH`` capable. If those
conditions are not met, no ``_scale_available`` attribute is provided.
Besides that, differential and pseudo-differential voltage channels present
slightly different sysfs interfaces.
Pseudo-differential ADCs
------------------------
Typical voltage channel attributes of a pseudo-differential AD4000 series device:
+-------------------------------------------+------------------------------------------+
| Voltage Channel Attributes | Description |
+===========================================+==========================================+
| ``in_voltage0_raw`` | Raw ADC output code. |
+-------------------------------------------+------------------------------------------+
| ``in_voltage0_offset`` | Offset to convert raw value to mV. |
+-------------------------------------------+------------------------------------------+
| ``in_voltage0_scale`` | Scale factor to convert raw value to mV. |
+-------------------------------------------+------------------------------------------+
| ``in_voltage0_scale_available`` | Toggles input span compression |
+-------------------------------------------+------------------------------------------+
Differential ADCs
-----------------
Typical voltage channel attributes of a differential AD4000 series device:
+-------------------------------------------+------------------------------------------+
| Voltage Channel Attributes | Description |
+===========================================+==========================================+
| ``in_voltage0-voltage1_raw`` | Raw ADC output code. |
+-------------------------------------------+------------------------------------------+
| ``in_voltage0-voltage1_scale`` | Scale factor to convert raw value to mV. |
+-------------------------------------------+------------------------------------------+
| ``in_voltage0-voltage1_scale_available`` | Toggles input span compression |
+-------------------------------------------+------------------------------------------+
SPI offload support
-------------------
To be able to achieve the maximum sample rate, the driver can be used with SPI
offload engines such as the one usually present in `AXI SPI Engine`_, to provide
SPI offload support.
.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/pulsar_adc/index.html
To keep up with SPI offloading transfer speeds, the ADC must be connected either
in 3-wire turbo mode or in 3-wire without busy indicator mode and have SPI
controller CS line connected to the CNV pin.
When set for SPI offload support, the IIO device will provide different
interfaces.
* Either ``in_voltage0_sampling_frequency`` or
``in_voltage0-voltage1_sampling_frequency`` file is provided to allow setting
the sample rate.
* IIO trigger device is not provided (no ``trigger`` directory).
* ``timestamp`` channel is not provided.
Also, because the ADC output has a one sample latency (delay) when the device is
wired in "3-wire" mode and only one transfer per sample is done when using SPI
offloading, the first data sample in the buffer is not valid because it contains
the output of an earlier conversion result.

View file

@ -27,6 +27,7 @@ The following chips are supported by this driver:
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
* `AD7389-4 <https://www.analog.com/en/products/ad7389-4.html>`_
* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
* `ADAQ4381-4 <https://www.analog.com/en/products/adaq4381-4.html>`_
@ -50,6 +51,12 @@ ad7380-4
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
declared in the device tree as ``refin-supply``.
ad7389-4
~~~~~~~~
ad7389-4 supports only an internal reference voltage. ``refin-supply`` and
``refio-supply`` properties are both omitted in this case.
ADAQ devices
~~~~~~~~~~~~

View file

@ -26,6 +26,35 @@ SPI wiring modes
These ADCs can output data on several SDO lines (1/2/4/8). The driver
currently supports only 1 SDO line.
SPI offload wiring
------------------
When used with a SPI offload, the supported wiring configuration is:
.. code-block::
+-------------+ +-------------+
| BUSY |-------->| TRIGGER |
| CS |<--------| CS |
| | | |
| ADC | | SPI |
| | | |
| SDI |<--------| SDO |
| DOUTA |-------->| SDI |
| SCLK |<--------| SCLK |
| | | |
| | +-------------+
| CONVST |<--------| PWM |
+-------------+ +-------------+
In this case, the ``pwms`` property is required.
The ``#trigger-source-cells = <1>`` property is also required to connect back
to the SPI offload. The SPI offload will have ``trigger-sources`` property
with a cell to indicate the busy signal:
``<&ad7606 AD4695_TRIGGER_EVENT_BUSY>``.
.. seealso:: `SPI offload support`_
Parallel wiring mode
--------------------
@ -123,6 +152,22 @@ Unimplemented features
- CRC indication
- Calibration
SPI offload support
===================
To be able to achieve the maximum sample rate, the driver can be used with the
`AXI SPI Engine`_ to provide SPI offload support.
.. _AXI SPI Engine: https://analogdevicesinc.github.io/hdl/library/spi_engine/index.html
When SPI offload is being used, some attributes will be different.
* ``trigger`` directory is removed.
* ``sampling_frequency`` attribute is added for setting the sample rate.
* ``timestamp`` channel is removed.
* Buffer data format may be different compared to when offload is not used,
e.g. the ``in_voltage0_type`` attribute.
Device buffers
==============

View file

@ -19,6 +19,7 @@ Industrial I/O Kernel Drivers
.. toctree::
:maxdepth: 1
ad3552r
ad4000
ad4030
ad4695

View file

@ -0,0 +1,99 @@
.. SPDX-License-Identifier: GPL-2.0
=======================
AMD SIDE BAND interface
=======================
Some AMD Zen based processors supports system management
functionality via side-band interface (SBI) called
Advanced Platform Management Link (APML). APML is an I2C/I3C
based 2-wire processor target interface. APML is used to
communicate with the Remote Management Interface
(SB Remote Management Interface (SB-RMI)
and SB Temperature Sensor Interface (SB-TSI)).
More details on the interface can be found in chapter
"5 Advanced Platform Management Link (APML)" of the family/model PPR [1]_.
.. [1] https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip
SBRMI device
============
apml_sbrmi driver under the drivers/misc/amd-sbi creates miscdevice
/dev/sbrmi-* to let user space programs run APML mailbox, CPUID,
MCAMSR and register xfer commands.
Register sets is common across APML protocols. IOCTL is providing synchronization
among protocols as transactions may create race condition.
$ ls -al /dev/sbrmi-3c
crw------- 1 root root 10, 53 Jul 10 11:13 /dev/sbrmi-3c
apml_sbrmi driver registers hwmon sensors for monitoring power_cap_max,
current power consumption and managing power_cap.
Characteristics of the dev node:
* Differnet xfer protocols are defined:
* Mailbox
* CPUID
* MCA_MSR
* Register xfer
Access restrictions:
* Only root user is allowed to open the file.
* APML Mailbox messages and Register xfer access are read-write,
* CPUID and MCA_MSR access is read-only.
Driver IOCTLs
=============
.. c:macro:: SBRMI_IOCTL_MBOX_CMD
.. kernel-doc:: include/uapi/misc/amd-apml.h
:doc: SBRMI_IOCTL_MBOX_CMD
.. c:macro:: SBRMI_IOCTL_CPUID_CMD
.. kernel-doc:: include/uapi/misc/amd-apml.h
:doc: SBRMI_IOCTL_CPUID_CMD
.. c:macro:: SBRMI_IOCTL_MCAMSR_CMD
.. kernel-doc:: include/uapi/misc/amd-apml.h
:doc: SBRMI_IOCTL_MCAMSR_CMD
.. c:macro:: SBRMI_IOCTL_REG_XFER_CMD
.. kernel-doc:: include/uapi/misc/amd-apml.h
:doc: SBRMI_IOCTL_REG_XFER_CMD
User-space usage
================
To access side band interface from a C program.
First, user need to include the headers::
#include <uapi/misc/amd-apml.h>
Which defines the supported IOCTL and data structure to be passed
from the user space.
Next thing, open the device file, as follows::
int file;
file = open("/dev/sbrmi-*", O_RDWR);
if (file < 0) {
/* ERROR HANDLING */
exit(1);
}
The following IOCTLs are defined:
``#define SB_BASE_IOCTL_NR 0xF9``
``#define SBRMI_IOCTL_MBOX_CMD _IOWR(SB_BASE_IOCTL_NR, 0, struct apml_mbox_msg)``
``#define SBRMI_IOCTL_CPUID_CMD _IOWR(SB_BASE_IOCTL_NR, 1, struct apml_cpuid_msg)``
``#define SBRMI_IOCTL_MCAMSR_CMD _IOWR(SB_BASE_IOCTL_NR, 2, struct apml_mcamsr_msg)``
``#define SBRMI_IOCTL_REG_XFER_CMD _IOWR(SB_BASE_IOCTL_NR, 3, struct apml_reg_xfer_msg)``
User space C-APIs are made available by esmi_oob_library, hosted at
[2]_ which is provided by the E-SMS project [3]_.
.. [2] https://github.com/amd/esmi_oob_library
.. [3] https://www.amd.com/en/developer/e-sms.html

View file

@ -12,6 +12,7 @@ fit into other categories.
:maxdepth: 2
ad525x_dpot
amd-sbi
apds990x
bh1770glc
c2port

View file

@ -22,10 +22,10 @@ sporting the feature officially called "HP Mobile Data Protection System 3D" or
models (full list can be found in drivers/platform/x86/hp_accel.c) will have
their axis automatically oriented on standard way (eg: you can directly play
neverball). The accelerometer data is readable via
/sys/devices/platform/lis3lv02d. Reported values are scaled
/sys/devices/faux/lis3lv02d. Reported values are scaled
to mg values (1/1000th of earth gravity).
Sysfs attributes under /sys/devices/platform/lis3lv02d/:
Sysfs attributes under /sys/devices/faux/lis3lv02d/:
position
- 3D position that the accelerometer reports. Format: "(x,y,z)"
@ -85,7 +85,7 @@ the accelerometer are converted into a "standard" organisation of the axes
If your laptop model is not recognized (cf "dmesg"), you can send an
email to the maintainer to add it to the database. When reporting a new
laptop, please include the output of "dmidecode" plus the value of
/sys/devices/platform/lis3lv02d/position in these four cases.
/sys/devices/faux/lis3lv02d/position in these four cases.
Q&A
---

View file

@ -78,6 +78,37 @@ enabled like::
Please refer to the kernel configuration help for more information.
Fine-grained tracing with AUX pause and resume
----------------------------------------------
Arm CoreSight may generate a large amount of hardware trace data, which
will lead to overhead in recording and distract users when reviewing
profiling result. To mitigate the issue of excessive trace data, Perf
provides AUX pause and resume functionality for fine-grained tracing.
The AUX pause and resume can be triggered by associated events. These
events can be ftrace tracepoints (including static and dynamic
tracepoints) or PMU events (e.g. CPU PMU cycle event). To create a perf
session with AUX pause / resume, three configuration terms are
introduced:
- "aux-action=start-paused": it is specified for the cs_etm PMU event to
launch in a paused state.
- "aux-action=pause": an associated event is specified with this term
to pause AUX trace.
- "aux-action=resume": an associated event is specified with this term
to resume AUX trace.
Example for triggering AUX pause and resume with ftrace tracepoints::
perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls
Example for triggering AUX pause and resume with PMU event::
perf record -a -e cs_etm/aux-action=start-paused/k \
-e cycles/aux-action=pause,period=10000000/ \
-e cycles/aux-action=resume,period=1050000/ -- sleep 1
Perf test - Verify kernel and userspace perf CoreSight work
-----------------------------------------------------------

View file

@ -402,6 +402,8 @@ Code Seq# Include File Comments
<mailto:mathieu.desnoyers@efficios.com>
0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver
<mailto:nchatrad@amd.com>
0xF9 00-0F uapi/misc/amd-apml.h AMD side band system management interface driver
<mailto:naveenkrishna.chatradhi@amd.com>
0xFD all linux/dm-ioctl.h
0xFE all linux/isst_if.h
==== ===== ======================================================= ================================================================

View file

@ -1338,12 +1338,21 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
F: drivers/net/amt.c
ANALOG DEVICES INC AD3530R DRIVER
M: Kim Seer Paller <kimseer.paller@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/dac/adi,ad3530r.yaml
F: drivers/iio/dac/ad3530r.c
ANALOG DEVICES INC AD3552R DRIVER
M: Nuno Sá <nuno.sa@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
F: Documentation/iio/ad3552r.rst
F: drivers/iio/dac/ad3552r.c
ANALOG DEVICES INC AD4000 DRIVER
@ -1387,6 +1396,16 @@ F: Documentation/iio/ad4695.rst
F: drivers/iio/adc/ad4695.c
F: include/dt-bindings/iio/adc/adi,ad4695.h
ANALOG DEVICES INC AD4851 DRIVER
M: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
M: Dragos Bogdan <dragos.bogdan@analog.com>
R: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
F: drivers/iio/adc/ad4851.c
ANALOG DEVICES INC AD7091R DRIVER
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
L: linux-iio@vger.kernel.org
@ -2322,11 +2341,13 @@ F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml
F: Documentation/devicetree/bindings/net/bluetooth/brcm,bcm4377-bluetooth.yaml
F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
F: Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
F: arch/arm64/boot/dts/apple/
F: drivers/bluetooth/hci_bcm4377.c
@ -2342,10 +2363,12 @@ F: drivers/iommu/io-pgtable-dart.c
F: drivers/irqchip/irq-apple-aic.c
F: drivers/nvme/host/apple.c
F: drivers/nvmem/apple-efuses.c
F: drivers/nvmem/apple-spmi-nvmem.c
F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/pwm/pwm-apple.c
F: drivers/soc/apple/*
F: drivers/spi/spi-apple.c
F: drivers/spmi/spmi-apple-controller.c
F: drivers/video/backlight/apple_dwi_bl.c
F: drivers/watchdog/apple_wdt.c
F: include/dt-bindings/interrupt-controller/apple-aic.h
@ -6938,6 +6961,12 @@ L: linux-rtc@vger.kernel.org
S: Maintained
F: drivers/rtc/rtc-sd2405al.c
DFROBOT SEN0322 DRIVER
M: Tóth János <gomba007@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/chemical/sen0322.c
DH ELECTRONICS DHSOM SOM AND BOARD SUPPORT
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
M: Marek Vasut <marex@denx.de>
@ -11644,6 +11673,13 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/rc/iguanair.c
IIO ADC HELPERS
M: Matti Vaittinen <mazziesaccount@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/adc/industrialio-adc.c
F: include/linux/iio/adc-helpers.h
IIO BACKEND FRAMEWORK
M: Nuno Sa <nuno.sa@analog.com>
R: Olivier Moysan <olivier.moysan@foss.st.com>
@ -11692,7 +11728,9 @@ F: drivers/iio/common/scmi_sensors/scmi_iio.c
IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@kernel.org>
R: Lars-Peter Clausen <lars@metafoo.de>
R: David Lechner <dlechner@baylibre.com>
R: Nuno Sá <nuno.sa@analog.com>
R: Andy Shevchenko <andy@kernel.org>
L: linux-iio@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
@ -12285,7 +12323,7 @@ F: drivers/mfd/intel-m10-bmc*
F: include/linux/mfd/intel-m10-bmc.h
INTEL MAX10 BMC SECURE UPDATES
M: Peter Colberg <peter.colberg@altera.com>
M: Matthew Gerlach <matthew.gerlach@altera.com>
L: linux-fpga@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
@ -16938,7 +16976,7 @@ F: include/uapi/linux/mmc/
MULTIPLEXER SUBSYSTEM
M: Peter Rosin <peda@axentia.se>
S: Maintained
S: Odd Fixes
F: Documentation/ABI/testing/sysfs-class-mux*
F: Documentation/devicetree/bindings/mux/
F: drivers/mux/
@ -17715,6 +17753,13 @@ F: drivers/nubus/
F: include/linux/nubus.h
F: include/uapi/linux/nubus.h
NUVOTON NCT7201 IIO DRIVER
M: Eason Yang <j2anfernee@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/adc/nuvoton,nct7201.yaml
F: drivers/iio/adc/nct7201.c
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
@ -21445,6 +21490,11 @@ S: Supported
F: drivers/power/supply/bd99954-charger.c
F: drivers/power/supply/bd99954-charger.h
ROHM BD79124 ADC / GPO IC
M: Matti Vaittinen <mazziesaccount@gmail.com>
S: Supported
F: drivers/iio/adc/rohm-bd79124.c
ROHM BH1745 COLOUR SENSOR
M: Mudit Sharma <muditsharma.info@gmail.com>
L: linux-iio@vger.kernel.org
@ -24646,6 +24696,12 @@ M: Robert Richter <rric@kernel.org>
S: Odd Fixes
F: drivers/gpio/gpio-thunderx.c
TI ADC12xs and ROHM BD79104 ADC driver
M: Matti Vaittinen <mazziesaccount@gmail.com>
S: Maintained
F: drivers/iio/adc/ti-adc128s052.c
L: linux-iio@vger.kernel.org
TI ADS1119 ADC DRIVER
M: Francesco Dolcini <francesco@dolcini.it>
M: João Paulo Gonçalves <jpaulo.silvagoncalves@gmail.com>
@ -26595,6 +26651,12 @@ M: David Härdeman <david@hardeman.nu>
S: Maintained
F: drivers/media/rc/winbond-cir.c
WINSEN MHZ19B
M: Gyeyoung Baek <gye976@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/iio/chemical/winsen,mhz19b.yaml
F: drivers/iio/chemical/mhz19b.c
WINSYSTEMS EBC-C384 WATCHDOG DRIVER
L: linux-watchdog@vger.kernel.org
S: Orphan
@ -27092,8 +27154,6 @@ M: Dragan Cvetic <dragan.cvetic@amd.com>
S: Maintained
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.yaml
F: Documentation/misc-devices/xilinx_sdfec.rst
F: drivers/misc/Kconfig
F: drivers/misc/Makefile
F: drivers/misc/xilinx_sdfec.c
F: include/uapi/misc/xilinx_sdfec.h

View file

@ -79,6 +79,8 @@ static HLIST_HEAD(binder_deferred_list);
static DEFINE_MUTEX(binder_deferred_lock);
static HLIST_HEAD(binder_devices);
static DEFINE_SPINLOCK(binder_devices_lock);
static HLIST_HEAD(binder_procs);
static DEFINE_MUTEX(binder_procs_lock);
@ -3261,20 +3263,16 @@ static void binder_transaction(struct binder_proc *proc,
if (reply)
binder_debug(BINDER_DEBUG_TRANSACTION,
"%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
"%d:%d BC_REPLY %d -> %d:%d, data size %lld-%lld-%lld\n",
proc->pid, thread->pid, t->debug_id,
target_proc->pid, target_thread->pid,
(u64)tr->data.ptr.buffer,
(u64)tr->data.ptr.offsets,
(u64)tr->data_size, (u64)tr->offsets_size,
(u64)extra_buffers_size);
else
binder_debug(BINDER_DEBUG_TRANSACTION,
"%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
"%d:%d BC_TRANSACTION %d -> %d - node %d, data size %lld-%lld-%lld\n",
proc->pid, thread->pid, t->debug_id,
target_proc->pid, target_node->debug_id,
(u64)tr->data.ptr.buffer,
(u64)tr->data.ptr.offsets,
(u64)tr->data_size, (u64)tr->offsets_size,
(u64)extra_buffers_size);
@ -4223,20 +4221,21 @@ static int binder_thread_write(struct binder_proc *proc,
if (IS_ERR_OR_NULL(buffer)) {
if (PTR_ERR(buffer) == -EPERM) {
binder_user_error(
"%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n",
"%d:%d BC_FREE_BUFFER matched unreturned or currently freeing buffer at offset %lx\n",
proc->pid, thread->pid,
(u64)data_ptr);
(unsigned long)data_ptr - proc->alloc.vm_start);
} else {
binder_user_error(
"%d:%d BC_FREE_BUFFER u%016llx no match\n",
"%d:%d BC_FREE_BUFFER no match for buffer at offset %lx\n",
proc->pid, thread->pid,
(u64)data_ptr);
(unsigned long)data_ptr - proc->alloc.vm_start);
}
break;
}
binder_debug(BINDER_DEBUG_FREE_BUFFER,
"%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
proc->pid, thread->pid, (u64)data_ptr,
"%d:%d BC_FREE_BUFFER at offset %lx found buffer %d for %s transaction\n",
proc->pid, thread->pid,
(unsigned long)data_ptr - proc->alloc.vm_start,
buffer->debug_id,
buffer->transaction ? "active" : "finished");
binder_free_buf(proc, thread, buffer, false);
@ -5053,16 +5052,14 @@ retry:
trace_binder_transaction_received(t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_TRANSACTION,
"%d:%d %s %d %d:%d, cmd %u size %zd-%zd ptr %016llx-%016llx\n",
"%d:%d %s %d %d:%d, cmd %u size %zd-%zd\n",
proc->pid, thread->pid,
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
(cmd == BR_TRANSACTION_SEC_CTX) ?
"BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
t->debug_id, t_from ? t_from->proc->pid : 0,
t_from ? t_from->pid : 0, cmd,
t->buffer->data_size, t->buffer->offsets_size,
(u64)trd->data.ptr.buffer,
(u64)trd->data.ptr.offsets);
t->buffer->data_size, t->buffer->offsets_size);
if (t_from)
binder_thread_dec_tmpref(t_from);
@ -5244,6 +5241,7 @@ static void binder_free_proc(struct binder_proc *proc)
__func__, proc->outstanding_txns);
device = container_of(proc->context, struct binder_device, context);
if (refcount_dec_and_test(&device->ref)) {
binder_remove_device(device);
kfree(proc->context->name);
kfree(device);
}
@ -6380,7 +6378,7 @@ static void print_binder_work_ilocked(struct seq_file *m,
struct binder_proc *proc,
const char *prefix,
const char *transaction_prefix,
struct binder_work *w)
struct binder_work *w, bool hash_ptrs)
{
struct binder_node *node;
struct binder_transaction *t;
@ -6403,6 +6401,12 @@ static void print_binder_work_ilocked(struct seq_file *m,
break;
case BINDER_WORK_NODE:
node = container_of(w, struct binder_node, work);
if (hash_ptrs)
seq_printf(m, "%snode work %d: u%p c%p\n",
prefix, node->debug_id,
(void *)(long)node->ptr,
(void *)(long)node->cookie);
else
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
prefix, node->debug_id,
(u64)node->ptr, (u64)node->cookie);
@ -6430,7 +6434,7 @@ static void print_binder_work_ilocked(struct seq_file *m,
static void print_binder_thread_ilocked(struct seq_file *m,
struct binder_thread *thread,
int print_always)
bool print_always, bool hash_ptrs)
{
struct binder_transaction *t;
struct binder_work *w;
@ -6460,14 +6464,16 @@ static void print_binder_thread_ilocked(struct seq_file *m,
}
list_for_each_entry(w, &thread->todo, entry) {
print_binder_work_ilocked(m, thread->proc, " ",
" pending transaction", w);
" pending transaction",
w, hash_ptrs);
}
if (!print_always && m->count == header_pos)
m->count = start_pos;
}
static void print_binder_node_nilocked(struct seq_file *m,
struct binder_node *node)
struct binder_node *node,
bool hash_ptrs)
{
struct binder_ref *ref;
struct binder_work *w;
@ -6475,8 +6481,13 @@ static void print_binder_node_nilocked(struct seq_file *m,
count = hlist_count_nodes(&node->refs);
seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d",
node->debug_id, (u64)node->ptr, (u64)node->cookie,
if (hash_ptrs)
seq_printf(m, " node %d: u%p c%p", node->debug_id,
(void *)(long)node->ptr, (void *)(long)node->cookie);
else
seq_printf(m, " node %d: u%016llx c%016llx", node->debug_id,
(u64)node->ptr, (u64)node->cookie);
seq_printf(m, " hs %d hw %d ls %d lw %d is %d iw %d tr %d",
node->has_strong_ref, node->has_weak_ref,
node->local_strong_refs, node->local_weak_refs,
node->internal_strong_refs, count, node->tmp_refs);
@ -6489,7 +6500,8 @@ static void print_binder_node_nilocked(struct seq_file *m,
if (node->proc) {
list_for_each_entry(w, &node->async_todo, entry)
print_binder_work_ilocked(m, node->proc, " ",
" pending async transaction", w);
" pending async transaction",
w, hash_ptrs);
}
}
@ -6505,8 +6517,54 @@ static void print_binder_ref_olocked(struct seq_file *m,
binder_node_unlock(ref->node);
}
static void print_binder_proc(struct seq_file *m,
struct binder_proc *proc, int print_all)
/**
* print_next_binder_node_ilocked() - Print binder_node from a locked list
* @m: struct seq_file for output via seq_printf()
* @proc: struct binder_proc we hold the inner_proc_lock to (if any)
* @node: struct binder_node to print fields of
* @prev_node: struct binder_node we hold a temporary reference to (if any)
* @hash_ptrs: whether to hash @node's binder_uintptr_t fields
*
* Helper function to handle synchronization around printing a struct
* binder_node while iterating through @proc->nodes or the dead nodes list.
* Caller must hold either @proc->inner_lock (for live nodes) or
* binder_dead_nodes_lock. This lock will be released during the body of this
* function, but it will be reacquired before returning to the caller.
*
* Return: pointer to the struct binder_node we hold a tmpref on
*/
static struct binder_node *
print_next_binder_node_ilocked(struct seq_file *m, struct binder_proc *proc,
struct binder_node *node,
struct binder_node *prev_node, bool hash_ptrs)
{
/*
* Take a temporary reference on the node so that isn't freed while
* we print it.
*/
binder_inc_node_tmpref_ilocked(node);
/*
* Live nodes need to drop the inner proc lock and dead nodes need to
* drop the binder_dead_nodes_lock before trying to take the node lock.
*/
if (proc)
binder_inner_proc_unlock(proc);
else
spin_unlock(&binder_dead_nodes_lock);
if (prev_node)
binder_put_node(prev_node);
binder_node_inner_lock(node);
print_binder_node_nilocked(m, node, hash_ptrs);
binder_node_inner_unlock(node);
if (proc)
binder_inner_proc_lock(proc);
else
spin_lock(&binder_dead_nodes_lock);
return node;
}
static void print_binder_proc(struct seq_file *m, struct binder_proc *proc,
bool print_all, bool hash_ptrs)
{
struct binder_work *w;
struct rb_node *n;
@ -6519,31 +6577,19 @@ static void print_binder_proc(struct seq_file *m,
header_pos = m->count;
binder_inner_proc_lock(proc);
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
for (n = rb_first(&proc->threads); n; n = rb_next(n))
print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread,
rb_node), print_all);
rb_node), print_all, hash_ptrs);
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
struct binder_node *node = rb_entry(n, struct binder_node,
rb_node);
if (!print_all && !node->has_async_transaction)
continue;
/*
* take a temporary reference on the node so it
* survives and isn't removed from the tree
* while we print it.
*/
binder_inc_node_tmpref_ilocked(node);
/* Need to drop inner lock to take node lock */
binder_inner_proc_unlock(proc);
if (last_node)
binder_put_node(last_node);
binder_node_inner_lock(node);
print_binder_node_nilocked(m, node);
binder_node_inner_unlock(node);
last_node = node;
binder_inner_proc_lock(proc);
last_node = print_next_binder_node_ilocked(m, proc, node,
last_node,
hash_ptrs);
}
binder_inner_proc_unlock(proc);
if (last_node)
@ -6551,9 +6597,7 @@ static void print_binder_proc(struct seq_file *m,
if (print_all) {
binder_proc_lock(proc);
for (n = rb_first(&proc->refs_by_desc);
n != NULL;
n = rb_next(n))
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n))
print_binder_ref_olocked(m, rb_entry(n,
struct binder_ref,
rb_node_desc));
@ -6563,7 +6607,8 @@ static void print_binder_proc(struct seq_file *m,
binder_inner_proc_lock(proc);
list_for_each_entry(w, &proc->todo, entry)
print_binder_work_ilocked(m, proc, " ",
" pending transaction", w);
" pending transaction", w,
hash_ptrs);
list_for_each_entry(w, &proc->delivered_death, entry) {
seq_puts(m, " has delivered dead binder\n");
break;
@ -6696,7 +6741,7 @@ static void print_binder_proc_stats(struct seq_file *m,
count = 0;
ready_threads = 0;
binder_inner_proc_lock(proc);
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
for (n = rb_first(&proc->threads); n; n = rb_next(n))
count++;
list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
@ -6710,7 +6755,7 @@ static void print_binder_proc_stats(struct seq_file *m,
ready_threads,
free_async_space);
count = 0;
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
for (n = rb_first(&proc->nodes); n; n = rb_next(n))
count++;
binder_inner_proc_unlock(proc);
seq_printf(m, " nodes: %d\n", count);
@ -6718,7 +6763,7 @@ static void print_binder_proc_stats(struct seq_file *m,
strong = 0;
weak = 0;
binder_proc_lock(proc);
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) {
struct binder_ref *ref = rb_entry(n, struct binder_ref,
rb_node_desc);
count++;
@ -6745,7 +6790,7 @@ static void print_binder_proc_stats(struct seq_file *m,
print_binder_stats(m, " ", &proc->stats);
}
static int state_show(struct seq_file *m, void *unused)
static void print_binder_state(struct seq_file *m, bool hash_ptrs)
{
struct binder_proc *proc;
struct binder_node *node;
@ -6756,31 +6801,40 @@ static int state_show(struct seq_file *m, void *unused)
spin_lock(&binder_dead_nodes_lock);
if (!hlist_empty(&binder_dead_nodes))
seq_puts(m, "dead nodes:\n");
hlist_for_each_entry(node, &binder_dead_nodes, dead_node) {
/*
* take a temporary reference on the node so it
* survives and isn't removed from the list
* while we print it.
*/
node->tmp_refs++;
spin_unlock(&binder_dead_nodes_lock);
if (last_node)
binder_put_node(last_node);
binder_node_lock(node);
print_binder_node_nilocked(m, node);
binder_node_unlock(node);
last_node = node;
spin_lock(&binder_dead_nodes_lock);
}
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
last_node = print_next_binder_node_ilocked(m, NULL, node,
last_node,
hash_ptrs);
spin_unlock(&binder_dead_nodes_lock);
if (last_node)
binder_put_node(last_node);
mutex_lock(&binder_procs_lock);
hlist_for_each_entry(proc, &binder_procs, proc_node)
print_binder_proc(m, proc, 1);
print_binder_proc(m, proc, true, hash_ptrs);
mutex_unlock(&binder_procs_lock);
}
static void print_binder_transactions(struct seq_file *m, bool hash_ptrs)
{
struct binder_proc *proc;
seq_puts(m, "binder transactions:\n");
mutex_lock(&binder_procs_lock);
hlist_for_each_entry(proc, &binder_procs, proc_node)
print_binder_proc(m, proc, false, hash_ptrs);
mutex_unlock(&binder_procs_lock);
}
static int state_show(struct seq_file *m, void *unused)
{
print_binder_state(m, false);
return 0;
}
static int state_hashed_show(struct seq_file *m, void *unused)
{
print_binder_state(m, true);
return 0;
}
@ -6802,14 +6856,13 @@ static int stats_show(struct seq_file *m, void *unused)
static int transactions_show(struct seq_file *m, void *unused)
{
struct binder_proc *proc;
seq_puts(m, "binder transactions:\n");
mutex_lock(&binder_procs_lock);
hlist_for_each_entry(proc, &binder_procs, proc_node)
print_binder_proc(m, proc, 0);
mutex_unlock(&binder_procs_lock);
print_binder_transactions(m, false);
return 0;
}
static int transactions_hashed_show(struct seq_file *m, void *unused)
{
print_binder_transactions(m, true);
return 0;
}
@ -6822,7 +6875,7 @@ static int proc_show(struct seq_file *m, void *unused)
hlist_for_each_entry(itr, &binder_procs, proc_node) {
if (itr->pid == pid) {
seq_puts(m, "binder proc state:\n");
print_binder_proc(m, itr, 1);
print_binder_proc(m, itr, true, false);
}
}
mutex_unlock(&binder_procs_lock);
@ -6889,8 +6942,10 @@ const struct file_operations binder_fops = {
};
DEFINE_SHOW_ATTRIBUTE(state);
DEFINE_SHOW_ATTRIBUTE(state_hashed);
DEFINE_SHOW_ATTRIBUTE(stats);
DEFINE_SHOW_ATTRIBUTE(transactions);
DEFINE_SHOW_ATTRIBUTE(transactions_hashed);
DEFINE_SHOW_ATTRIBUTE(transaction_log);
const struct binder_debugfs_entry binder_debugfs_entries[] = {
@ -6900,6 +6955,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
.fops = &state_fops,
.data = NULL,
},
{
.name = "state_hashed",
.mode = 0444,
.fops = &state_hashed_fops,
.data = NULL,
},
{
.name = "stats",
.mode = 0444,
@ -6912,6 +6973,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
.fops = &transactions_fops,
.data = NULL,
},
{
.name = "transactions_hashed",
.mode = 0444,
.fops = &transactions_hashed_fops,
.data = NULL,
},
{
.name = "transaction_log",
.mode = 0444,
@ -6929,7 +6996,16 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
void binder_add_device(struct binder_device *device)
{
spin_lock(&binder_devices_lock);
hlist_add_head(&device->hlist, &binder_devices);
spin_unlock(&binder_devices_lock);
}
void binder_remove_device(struct binder_device *device)
{
spin_lock(&binder_devices_lock);
hlist_del_init(&device->hlist);
spin_unlock(&binder_devices_lock);
}
static int __init init_binder_device(const char *name)
@ -6956,7 +7032,7 @@ static int __init init_binder_device(const char *name)
return ret;
}
hlist_add_head(&binder_device->hlist, &binder_devices);
binder_add_device(binder_device);
return ret;
}
@ -7018,7 +7094,7 @@ static int __init binder_init(void)
err_init_binder_device_failed:
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
misc_deregister(&device->miscdev);
hlist_del(&device->hlist);
binder_remove_device(device);
kfree(device);
}

View file

@ -583,9 +583,13 @@ struct binder_object {
/**
* Add a binder device to binder_devices
* @device: the new binder device to add to the global list
*
* Not reentrant as the list is not protected by any locks
*/
void binder_add_device(struct binder_device *device);
/**
* Remove a binder device to binder_devices
* @device: the binder device to remove from the global list
*/
void binder_remove_device(struct binder_device *device);
#endif /* _LINUX_BINDER_INTERNAL_H */

View file

@ -274,7 +274,7 @@ static void binderfs_evict_inode(struct inode *inode)
mutex_unlock(&binderfs_minors_mutex);
if (refcount_dec_and_test(&device->ref)) {
hlist_del_init(&device->hlist);
binder_remove_device(device);
kfree(device->context.name);
kfree(device);
}

View file

@ -945,6 +945,33 @@ unsigned int fwnode_get_child_node_count(const struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL_GPL(fwnode_get_child_node_count);
/**
* fwnode_get_named_child_node_count - number of child nodes with given name
* @fwnode: Node which child nodes are counted.
* @name: String to match child node name against.
*
* Scan child nodes and count all the nodes with a specific name. Potential
* 'number' -ending after the 'at sign' for scanned names is ignored.
* E.g.::
* fwnode_get_named_child_node_count(fwnode, "channel");
* would match all the nodes::
* channel { }, channel@0 {}, channel@0xabba {}...
*
* Return: the number of child nodes with a matching name for a given device.
*/
unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
const char *name)
{
struct fwnode_handle *child;
unsigned int count = 0;
fwnode_for_each_named_child_node(fwnode, child, name)
count++;
return count;
}
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node_count);
bool device_dma_supported(const struct device *dev)
{
return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);

View file

@ -131,19 +131,23 @@ int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *e
}
old_offset = ring->rd_offset;
mhi_ep_ring_inc_index(ring);
dev_dbg(dev, "Adding an element to ring at offset (%zu)\n", ring->rd_offset);
buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
buf_info.dev_addr = el;
buf_info.size = sizeof(*el);
ret = mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
if (ret)
return ret;
mhi_ep_ring_inc_index(ring);
/* Update rp in ring context */
rp = cpu_to_le64(ring->rd_offset * sizeof(*el) + ring->rbase);
memcpy_toio((void __iomem *) &ring->ring_ctx->generic.rp, &rp, sizeof(u64));
buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
buf_info.dev_addr = el;
buf_info.size = sizeof(*el);
return mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
return ret;
}
void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id)

View file

@ -782,6 +782,42 @@ static const struct mhi_pci_dev_info mhi_telit_fe990a_info = {
.mru_default = 32768,
};
static const struct mhi_channel_config mhi_telit_fn920c04_channels[] = {
MHI_CHANNEL_CONFIG_UL_SBL(2, "SAHARA", 32, 0),
MHI_CHANNEL_CONFIG_DL_SBL(3, "SAHARA", 32, 0),
MHI_CHANNEL_CONFIG_UL(4, "DIAG", 64, 1),
MHI_CHANNEL_CONFIG_DL(5, "DIAG", 64, 1),
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(32, "DUN", 32, 0),
MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1),
MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
};
static const struct mhi_controller_config modem_telit_fn920c04_config = {
.max_channels = 128,
.timeout_ms = 50000,
.num_channels = ARRAY_SIZE(mhi_telit_fn920c04_channels),
.ch_cfg = mhi_telit_fn920c04_channels,
.num_events = ARRAY_SIZE(mhi_telit_fn990_events),
.event_cfg = mhi_telit_fn990_events,
};
static const struct mhi_pci_dev_info mhi_telit_fn920c04_info = {
.name = "telit-fn920c04",
.config = &modem_telit_fn920c04_config,
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
.dma_data_width = 32,
.sideband_wake = false,
.mru_default = 32768,
.edl_trigger = true,
};
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
.name = "netprisma-lcur57",
.edl = "qcom/prog_firehose_sdx24.mbn",
@ -806,6 +842,9 @@ static const struct mhi_pci_dev_info mhi_netprisma_fcun69_info = {
static const struct pci_device_id mhi_pci_id_table[] = {
{PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0116),
.driver_data = (kernel_ulong_t) &mhi_qcom_sa8775p_info },
/* Telit FN920C04 (sdx35) */
{PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020),
.driver_data = (kernel_ulong_t) &mhi_telit_fn920c04_info },
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c),
@ -996,10 +1035,6 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
int err;
err = pci_assign_resource(pdev, bar_num);
if (err)
return err;
err = pcim_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "failed to enable pci device: %d\n", err);

View file

@ -602,6 +602,7 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
struct mhi_cmd *mhi_cmd;
struct mhi_event_ctxt *er_ctxt;
struct device *dev = &mhi_cntrl->mhi_dev->dev;
bool reset_device = false;
int ret, i;
dev_dbg(dev, "Transitioning from PM state: %s to: %s\n",
@ -630,8 +631,23 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
/* Wake up threads waiting for state transition */
wake_up_all(&mhi_cntrl->state_event);
/* Trigger MHI RESET so that the device will not access host memory */
if (MHI_REG_ACCESS_VALID(prev_state)) {
/*
* If the device is in PBL or SBL, it will only respond to
* RESET if the device is in SYSERR state. SYSERR might
* already be cleared at this point.
*/
enum mhi_state cur_state = mhi_get_mhi_state(mhi_cntrl);
enum mhi_ee_type cur_ee = mhi_get_exec_env(mhi_cntrl);
if (cur_state == MHI_STATE_SYS_ERR)
reset_device = true;
else if (cur_ee != MHI_EE_PBL && cur_ee != MHI_EE_SBL)
reset_device = true;
}
/* Trigger MHI RESET so that the device will not access host memory */
if (reset_device) {
u32 in_reset = -1;
unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms);

View file

@ -165,7 +165,7 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
struct device_node *parent_node;
struct irq_domain *parent;
fwnode_handle = of_node_to_fwnode(np);
fwnode_handle = of_fwnode_handle(np);
parent_node = of_parse_phandle(np, "msi-map", 1);
if (!parent_node) {
@ -173,7 +173,7 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
return NULL;
}
parent = irq_find_matching_fwnode(of_node_to_fwnode(parent_node), DOMAIN_BUS_NEXUS);
parent = irq_find_matching_fwnode(of_fwnode_handle(parent_node), DOMAIN_BUS_NEXUS);
if (!parent || !msi_get_domain_info(parent)) {
dev_err(dev, "unable to locate ITS domain\n");
return NULL;

View file

@ -404,7 +404,7 @@ config TELCLOCK
configuration of the telecom clock configuration settings. This
device is used for hardware synchronization across the ATCA backplane
fabric. Upon loading, the driver exports a sysfs directory,
/sys/devices/platform/telco_clock, with a number of files for
/sys/devices/faux/telco_clock, with a number of files for
controlling the behavior of this hardware.
source "drivers/s390/char/Kconfig"

View file

@ -141,9 +141,6 @@ static struct apm_queue kapmd_queue;
static DEFINE_MUTEX(state_lock);
static const char driver_version[] = "1.13"; /* no spaces */
/*
* Compatibility cruft until the IPAQ people move over to the new
@ -435,6 +432,8 @@ static struct miscdevice apm_device = {
*/
static int proc_apm_show(struct seq_file *m, void *v)
{
static const char driver_version[] = "1.13"; /* no spaces */
struct apm_power_info info;
char *units;

View file

@ -1023,7 +1023,6 @@ static int __init hpet_init(void)
result = acpi_bus_register_driver(&hpet_acpi_driver);
if (result < 0) {
if (sysctl_header)
unregister_sysctl_table(sysctl_header);
misc_deregister(&hpet_misc);
return result;

View file

@ -58,9 +58,8 @@ static LIST_HEAD(misc_list);
static DEFINE_MUTEX(misc_mtx);
/*
* Assigned numbers, used for dynamic minors
* Assigned numbers.
*/
#define DYNAMIC_MINORS 128 /* like dynamic majors */
static DEFINE_IDA(misc_minors_ida);
static int misc_minor_alloc(int minor)
@ -69,33 +68,16 @@ static int misc_minor_alloc(int minor)
if (minor == MISC_DYNAMIC_MINOR) {
/* allocate free id */
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
if (ret >= 0) {
ret = DYNAMIC_MINORS - ret - 1;
} else {
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
MINORMASK, GFP_KERNEL);
}
} else {
/* specific minor, check if it is in dynamic or misc dynamic range */
if (minor < DYNAMIC_MINORS) {
minor = DYNAMIC_MINORS - minor - 1;
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
} else if (minor > MISC_DYNAMIC_MINOR) {
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
} else {
/* case of non-dynamic minors, no need to allocate id */
ret = 0;
}
}
return ret;
}
static void misc_minor_free(int minor)
{
if (minor < DYNAMIC_MINORS)
ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
else if (minor > MISC_DYNAMIC_MINOR)
ida_free(&misc_minors_ida, minor);
}

View file

@ -1184,8 +1184,7 @@ static int xillybus_flush(struct file *filp, fl_owner_t id)
static void xillybus_autoflush(struct work_struct *work)
{
struct delayed_work *workitem = container_of(
work, struct delayed_work, work);
struct delayed_work *workitem = to_delayed_work(work);
struct xilly_channel *channel = container_of(
workitem, struct xilly_channel, rd_workitem);
int rc;

View file

@ -27,14 +27,12 @@ static void comedi_buf_map_kref_release(struct kref *kref)
if (bm->page_list) {
if (bm->dma_dir != DMA_NONE) {
/*
* DMA buffer was allocated as a single block.
* Address is in page_list[0].
*/
buf = &bm->page_list[0];
dma_free_coherent(bm->dma_hw_dev,
PAGE_SIZE * bm->n_pages,
buf->virt_addr, buf->dma_addr);
for (i = 0; i < bm->n_pages; i++) {
buf = &bm->page_list[i];
dma_free_coherent(bm->dma_hw_dev, PAGE_SIZE,
buf->virt_addr,
buf->dma_addr);
}
} else {
for (i = 0; i < bm->n_pages; i++) {
buf = &bm->page_list[i];
@ -56,13 +54,7 @@ static void __comedi_buf_free(struct comedi_device *dev,
struct comedi_buf_map *bm;
unsigned long flags;
if (async->prealloc_buf) {
if (s->async_dma_dir == DMA_NONE)
vunmap(async->prealloc_buf);
async->prealloc_buf = NULL;
async->prealloc_bufsz = 0;
}
spin_lock_irqsave(&s->spin_lock, flags);
bm = async->buf_map;
async->buf_map = NULL;
@ -94,26 +86,14 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
goto err;
if (bm->dma_dir != DMA_NONE) {
void *virt_addr;
dma_addr_t dma_addr;
/*
* Currently, the DMA buffer needs to be allocated as a
* single block so that it can be mmap()'ed.
*/
virt_addr = dma_alloc_coherent(bm->dma_hw_dev,
PAGE_SIZE * n_pages, &dma_addr,
GFP_KERNEL);
if (!virt_addr)
goto err;
for (i = 0; i < n_pages; i++) {
buf = &bm->page_list[i];
buf->virt_addr = virt_addr + (i << PAGE_SHIFT);
buf->dma_addr = dma_addr + (i << PAGE_SHIFT);
buf->virt_addr =
dma_alloc_coherent(bm->dma_hw_dev, PAGE_SIZE,
&buf->dma_addr, GFP_KERNEL);
if (!buf->virt_addr)
break;
}
bm->n_pages = i;
} else {
for (i = 0; i < n_pages; i++) {
buf = &bm->page_list[i];
@ -123,11 +103,10 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
SetPageReserved(virt_to_page(buf->virt_addr));
}
}
bm->n_pages = i;
if (i < n_pages)
goto err;
}
return bm;
@ -141,11 +120,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
unsigned int n_pages)
{
struct comedi_async *async = s->async;
struct page **pages = NULL;
struct comedi_buf_map *bm;
struct comedi_buf_page *buf;
unsigned long flags;
unsigned int i;
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
dev_err(dev->class_dev,
@ -160,30 +136,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
spin_lock_irqsave(&s->spin_lock, flags);
async->buf_map = bm;
spin_unlock_irqrestore(&s->spin_lock, flags);
if (bm->dma_dir != DMA_NONE) {
/*
* DMA buffer was allocated as a single block.
* Address is in page_list[0].
*/
buf = &bm->page_list[0];
async->prealloc_buf = buf->virt_addr;
} else {
pages = vmalloc(sizeof(struct page *) * n_pages);
if (!pages)
return;
for (i = 0; i < n_pages; i++) {
buf = &bm->page_list[i];
pages[i] = virt_to_page(buf->virt_addr);
}
/* vmap the pages to prealloc_buf */
async->prealloc_buf = vmap(pages, n_pages, VM_MAP,
COMEDI_PAGE_PROTECTION);
vfree(pages);
}
async->prealloc_bufsz = n_pages << PAGE_SHIFT;
}
void comedi_buf_map_get(struct comedi_buf_map *bm)
@ -264,7 +217,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
/* if no change is required, do nothing */
if (async->prealloc_buf && async->prealloc_bufsz == new_size)
if (async->prealloc_bufsz == new_size)
return 0;
/* deallocate old buffer */
@ -275,14 +228,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int n_pages = new_size >> PAGE_SHIFT;
__comedi_buf_alloc(dev, s, n_pages);
if (!async->prealloc_buf) {
/* allocation failed */
__comedi_buf_free(dev, s);
if (!async->prealloc_bufsz)
return -ENOMEM;
}
}
async->prealloc_bufsz = new_size;
return 0;
}
@ -365,6 +313,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
unsigned int num_bytes)
{
struct comedi_async *async = s->async;
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
unsigned int count = 0;
const unsigned int num_sample_bytes = comedi_bytes_per_sample(s);
@ -376,15 +325,16 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
/* don't munge partial samples */
num_bytes -= num_bytes % num_sample_bytes;
while (count < num_bytes) {
int block_size = num_bytes - count;
unsigned int buf_end;
/*
* Do not munge beyond page boundary.
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
*/
unsigned int page = async->munge_ptr >> PAGE_SHIFT;
unsigned int offset = offset_in_page(async->munge_ptr);
unsigned int block_size =
min(num_bytes - count, PAGE_SIZE - offset);
buf_end = async->prealloc_bufsz - async->munge_ptr;
if (block_size > buf_end)
block_size = buf_end;
s->munge(s->device, s,
async->prealloc_buf + async->munge_ptr,
s->munge(s->device, s, buf_page_list[page].virt_addr + offset,
block_size, async->munge_chan);
/*
@ -397,7 +347,8 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
async->munge_chan %= async->cmd.chanlist_len;
async->munge_count += block_size;
async->munge_ptr += block_size;
async->munge_ptr %= async->prealloc_bufsz;
if (async->munge_ptr == async->prealloc_bufsz)
async->munge_ptr = 0;
count += block_size;
}
@ -558,21 +509,25 @@ static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
const void *data, unsigned int num_bytes)
{
struct comedi_async *async = s->async;
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
unsigned int write_ptr = async->buf_write_ptr;
while (num_bytes) {
unsigned int block_size;
/*
* Do not copy beyond page boundary.
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
*/
unsigned int page = write_ptr >> PAGE_SHIFT;
unsigned int offset = offset_in_page(write_ptr);
unsigned int block_size = min(num_bytes, PAGE_SIZE - offset);
if (write_ptr + num_bytes > async->prealloc_bufsz)
block_size = async->prealloc_bufsz - write_ptr;
else
block_size = num_bytes;
memcpy(async->prealloc_buf + write_ptr, data, block_size);
memcpy(buf_page_list[page].virt_addr + offset,
data, block_size);
data += block_size;
num_bytes -= block_size;
write_ptr += block_size;
if (write_ptr == async->prealloc_bufsz)
write_ptr = 0;
}
}
@ -580,23 +535,25 @@ static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
void *dest, unsigned int nbytes)
{
void *src;
struct comedi_async *async = s->async;
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
unsigned int read_ptr = async->buf_read_ptr;
while (nbytes) {
unsigned int block_size;
/*
* Do not copy beyond page boundary.
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
*/
unsigned int page = read_ptr >> PAGE_SHIFT;
unsigned int offset = offset_in_page(read_ptr);
unsigned int block_size = min(nbytes, PAGE_SIZE - offset);
src = async->prealloc_buf + read_ptr;
if (nbytes >= async->prealloc_bufsz - read_ptr)
block_size = async->prealloc_bufsz - read_ptr;
else
block_size = nbytes;
memcpy(dest, src, block_size);
memcpy(dest, buf_page_list[page].virt_addr + offset,
block_size);
nbytes -= block_size;
dest += block_size;
read_ptr += block_size;
if (read_ptr == async->prealloc_bufsz)
read_ptr = 0;
}
}

View file

@ -2387,13 +2387,27 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
goto done;
}
if (bm->dma_dir != DMA_NONE) {
unsigned long vm_start = vma->vm_start;
unsigned long vm_end = vma->vm_end;
/*
* DMA buffer was allocated as a single block.
* Address is in page_list[0].
* Buffer pages are not contiguous, so temporarily modify VMA
* start and end addresses for each buffer page.
*/
buf = &bm->page_list[0];
retval = dma_mmap_coherent(bm->dma_hw_dev, vma, buf->virt_addr,
buf->dma_addr, n_pages * PAGE_SIZE);
for (i = 0; i < n_pages; ++i) {
buf = &bm->page_list[i];
vma->vm_start = start;
vma->vm_end = start + PAGE_SIZE;
retval = dma_mmap_coherent(bm->dma_hw_dev, vma,
buf->virt_addr,
buf->dma_addr, PAGE_SIZE);
if (retval)
break;
start += PAGE_SIZE;
}
vma->vm_start = vm_start;
vma->vm_end = vm_end;
} else {
for (i = 0; i < n_pages; ++i) {
unsigned long pfn;
@ -2407,19 +2421,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
start += PAGE_SIZE;
}
}
#ifdef CONFIG_MMU
/*
* Leaving behind a partial mapping of a buffer we're about to
* drop is unsafe, see remap_pfn_range_notrack().
* We need to zap the range here ourselves instead of relying
* on the automatic zapping in remap_pfn_range() because we call
* remap_pfn_range() in a loop.
* Leaving behind a partial mapping of a buffer we're about to drop is
* unsafe, see remap_pfn_range_notrack(). We need to zap the range
* here ourselves instead of relying on the automatic zapping in
* remap_pfn_range() because we call remap_pfn_range() in a loop.
*/
if (retval)
zap_vma_ptes(vma, vma->vm_start, size);
#endif
}
if (retval == 0) {
vma->vm_ops = &comedi_vm_ops;
@ -2475,6 +2488,62 @@ done:
return mask;
}
static unsigned int comedi_buf_copy_to_user(struct comedi_subdevice *s,
void __user *dest, unsigned int src_offset, unsigned int n)
{
struct comedi_buf_map *bm = s->async->buf_map;
struct comedi_buf_page *buf_page_list = bm->page_list;
unsigned int page = src_offset >> PAGE_SHIFT;
unsigned int offset = offset_in_page(src_offset);
while (n) {
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
unsigned int uncopied;
uncopied = copy_to_user(dest, buf_page_list[page].virt_addr +
offset, copy_amount);
copy_amount -= uncopied;
n -= copy_amount;
if (uncopied)
break;
dest += copy_amount;
page++;
if (page == bm->n_pages)
page = 0; /* buffer wraparound */
offset = 0;
}
return n;
}
static unsigned int comedi_buf_copy_from_user(struct comedi_subdevice *s,
unsigned int dst_offset, const void __user *src, unsigned int n)
{
struct comedi_buf_map *bm = s->async->buf_map;
struct comedi_buf_page *buf_page_list = bm->page_list;
unsigned int page = dst_offset >> PAGE_SHIFT;
unsigned int offset = offset_in_page(dst_offset);
while (n) {
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
unsigned int uncopied;
uncopied = copy_from_user(buf_page_list[page].virt_addr +
offset, src, copy_amount);
copy_amount -= uncopied;
n -= copy_amount;
if (uncopied)
break;
src += copy_amount;
page++;
if (page == bm->n_pages)
page = 0; /* buffer wraparound */
offset = 0;
}
return n;
}
static ssize_t comedi_write(struct file *file, const char __user *buf,
size_t nbytes, loff_t *offset)
{
@ -2516,7 +2585,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
add_wait_queue(&async->wait_head, &wait);
while (count == 0 && !retval) {
unsigned int runflags;
unsigned int wp, n1, n2;
set_current_state(TASK_INTERRUPTIBLE);
@ -2555,14 +2623,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
}
set_current_state(TASK_RUNNING);
wp = async->buf_write_ptr;
n1 = min(n, async->prealloc_bufsz - wp);
n2 = n - n1;
m = copy_from_user(async->prealloc_buf + wp, buf, n1);
if (m)
m += n2;
else if (n2)
m = copy_from_user(async->prealloc_buf, buf + n1, n2);
m = comedi_buf_copy_from_user(s, async->buf_write_ptr, buf, n);
if (m) {
n -= m;
retval = -EFAULT;
@ -2651,8 +2712,6 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
add_wait_queue(&async->wait_head, &wait);
while (count == 0 && !retval) {
unsigned int rp, n1, n2;
set_current_state(TASK_INTERRUPTIBLE);
m = comedi_buf_read_n_available(s);
@ -2689,14 +2748,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
}
set_current_state(TASK_RUNNING);
rp = async->buf_read_ptr;
n1 = min(n, async->prealloc_bufsz - rp);
n2 = n - n1;
m = copy_to_user(buf, async->prealloc_buf + rp, n1);
if (m)
m += n2;
else if (n2)
m = copy_to_user(buf + n1, async->prealloc_buf, n2);
m = comedi_buf_copy_to_user(s, buf, async->buf_read_ptr, n);
if (m) {
n -= m;
retval = -EFAULT;

View file

@ -32,7 +32,7 @@
* ranges).
*
* There are some hardware limitations:
* a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
* a) You can't use mixture of unipolar/bipolar ranges or differential/single
* ended inputs.
* b) DMA transfers must have the length aligned to two samples (32 bit),
* so there is some problems if cmd->chanlist_len is odd. This driver tries
@ -227,7 +227,7 @@ struct pci9118_private {
struct pci9118_dmabuf dmabuf[2];
int softsshdelay; /*
* >0 use software S&H,
* numer is requested delay in ns
* number is requested delay in ns
*/
unsigned char softsshsample; /*
* polarity of S&H signal

View file

@ -215,7 +215,7 @@ static const int ni_irqpin[] = {
#include "ni_mio_common.c"
static const struct pnp_device_id device_ids[] = {
static const struct pnp_device_id __maybe_unused device_ids[] = {
{.id = "NIC1900", .driver_data = 0},
{.id = "NIC2400", .driver_data = 0},
{.id = "NIC2500", .driver_data = 0},

View file

@ -747,8 +747,6 @@ static int ni_pcidio_change(struct comedi_device *dev,
if (ret < 0)
return ret;
memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
return 0;
}

View file

@ -3,22 +3,25 @@
* Copyright (c) 2021 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#include <linux/cleanup.h>
#include <linux/counter.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#define INTERRUPT_CNT_NAME "interrupt-cnt"
struct interrupt_cnt_priv {
atomic_t count;
atomic_long_t count;
struct gpio_desc *gpio;
int irq;
bool enabled;
struct mutex lock;
struct counter_signal signals;
struct counter_synapse synapses;
struct counter_count cnts;
@ -29,7 +32,7 @@ static irqreturn_t interrupt_cnt_isr(int irq, void *dev_id)
struct counter_device *counter = dev_id;
struct interrupt_cnt_priv *priv = counter_priv(counter);
atomic_inc(&priv->count);
atomic_long_inc(&priv->count);
counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE, 0);
@ -41,6 +44,8 @@ static int interrupt_cnt_enable_read(struct counter_device *counter,
{
struct interrupt_cnt_priv *priv = counter_priv(counter);
guard(mutex)(&priv->lock);
*enable = priv->enabled;
return 0;
@ -51,6 +56,8 @@ static int interrupt_cnt_enable_write(struct counter_device *counter,
{
struct interrupt_cnt_priv *priv = counter_priv(counter);
guard(mutex)(&priv->lock);
if (priv->enabled == enable)
return 0;
@ -89,7 +96,7 @@ static int interrupt_cnt_read(struct counter_device *counter,
{
struct interrupt_cnt_priv *priv = counter_priv(counter);
*val = atomic_read(&priv->count);
*val = atomic_long_read(&priv->count);
return 0;
}
@ -102,7 +109,7 @@ static int interrupt_cnt_write(struct counter_device *counter,
if (val != (typeof(priv->count.counter))val)
return -ERANGE;
atomic_set(&priv->count, val);
atomic_long_set(&priv->count, val);
return 0;
}
@ -227,6 +234,8 @@ static int interrupt_cnt_probe(struct platform_device *pdev)
if (ret)
return ret;
mutex_init(&priv->lock);
ret = devm_counter_add(dev, counter);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to add counter\n");

View file

@ -337,6 +337,28 @@ static struct counter_comp mchp_tc_count_ext[] = {
COUNTER_COMP_COMPARE(mchp_tc_count_compare_read, mchp_tc_count_compare_write),
};
static int mchp_tc_watch_validate(struct counter_device *counter,
const struct counter_watch *watch)
{
if (watch->channel == COUNTER_MCHP_EVCHN_CV || watch->channel == COUNTER_MCHP_EVCHN_RA)
switch (watch->event) {
case COUNTER_EVENT_CHANGE_OF_STATE:
case COUNTER_EVENT_OVERFLOW:
case COUNTER_EVENT_CAPTURE:
return 0;
default:
return -EINVAL;
}
if (watch->channel == COUNTER_MCHP_EVCHN_RB && watch->event == COUNTER_EVENT_CAPTURE)
return 0;
if (watch->channel == COUNTER_MCHP_EVCHN_RC && watch->event == COUNTER_EVENT_THRESHOLD)
return 0;
return -EINVAL;
}
static struct counter_count mchp_tc_counts[] = {
{
.id = 0,
@ -356,7 +378,8 @@ static const struct counter_ops mchp_tc_ops = {
.function_read = mchp_tc_count_function_read,
.function_write = mchp_tc_count_function_write,
.action_read = mchp_tc_count_action_read,
.action_write = mchp_tc_count_action_write
.action_write = mchp_tc_count_action_write,
.watch_validate = mchp_tc_watch_validate,
};
static const struct atmel_tcb_config tcb_rm9200_config = {

View file

@ -669,12 +669,14 @@ static void stm32_timer_cnt_detect_channels(struct device *dev,
dev_dbg(dev, "has %d cc channels\n", priv->nchannels);
}
/* encoder supported on TIM1 TIM2 TIM3 TIM4 TIM5 TIM8 */
#define STM32_TIM_ENCODER_SUPPORTED (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(7))
/* encoder supported on TIM1 TIM2 TIM3 TIM4 TIM5 TIM8 TIM20 */
#define STM32_TIM_ENCODER_SUPPORTED (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(7) | \
BIT(19))
static const char * const stm32_timer_trigger_compat[] = {
"st,stm32-timer-trigger",
"st,stm32h7-timer-trigger",
"st,stm32mp25-timer-trigger",
};
static int stm32_timer_cnt_probe_encoder(struct device *dev,
@ -846,6 +848,7 @@ static SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend,
static const struct of_device_id stm32_timer_cnt_of_match[] = {
{ .compatible = "st,stm32-timer-counter", },
{ .compatible = "st,stm32mp25-timer-counter", },
{},
};
MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for the Linux device tree
always-$(CONFIG_EISA) += devlist.h
obj-$(CONFIG_EISA) += eisa-bus.o
obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
@ -9,14 +10,11 @@ obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
# Ugly hack to get DEVICE_NAME_SIZE value...
DEVICE_NAME_SIZE = 50
$(obj)/eisa-bus.o: $(obj)/devlist.h
quiet_cmd_eisaid = GEN $@
cmd_eisaid = sed -e '/^\#/D' -e 's/^\([[:alnum:]]\{7\}\) \+"\([^"]\{1,$(DEVICE_NAME_SIZE)\}\).*"/EISA_DEVINFO ("\1", "\2"),/' $< > $@
cmd_eisaid = sed -e '/^\#/D' -e 's/^\([[:alnum:]]\{7\}\) \+"\([^"]*\)"/EISA_DEVINFO ("\1", "\2"),/' $< > $@
clean-files := devlist.h
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h
$(call cmd,eisaid)
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h FORCE
$(call if_changed,eisaid)

View file

@ -21,7 +21,7 @@
struct eisa_device_info {
struct eisa_device_id id;
char name[50];
char name[EISA_DEVICE_INFO_NAME_SIZE];
};
#ifdef CONFIG_EISA_NAMES

View file

@ -263,6 +263,7 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
img_buf = init_test_buffer(test, IMAGE_SIZE);
sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt);
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
KUNIT_ASSERT_EQ(test, ret, 0);
sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);

View file

@ -1905,16 +1905,6 @@ config SENSORS_SBTSI
This driver can also be built as a module. If so, the module will
be called sbtsi_temp.
config SENSORS_SBRMI
tristate "Emulated SB-RMI sensor"
depends on I2C
help
If you say yes here you get support for emulated RMI
sensors on AMD SoCs with APML interface connected to a BMC device.
This driver can also be built as a module. If so, the module will
be called sbrmi.
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB || COMPILE_TEST

View file

@ -1,357 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* sbrmi.c - hwmon driver for a SB-RMI mailbox
* compliant AMD SoC device.
*
* Copyright (C) 2020-2021 Advanced Micro Devices, Inc.
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
/* Do not allow setting negative power limit */
#define SBRMI_PWR_MIN 0
/* Mask for Status Register bit[1] */
#define SW_ALERT_MASK 0x2
/* Software Interrupt for triggering */
#define START_CMD 0x80
#define TRIGGER_MAILBOX 0x01
/*
* SB-RMI supports soft mailbox service request to MP1 (power management
* firmware) through SBRMI inbound/outbound message registers.
* SB-RMI message IDs
*/
enum sbrmi_msg_id {
SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1,
SBRMI_WRITE_PKG_PWR_LIMIT,
SBRMI_READ_PKG_PWR_LIMIT,
SBRMI_READ_PKG_MAX_PWR_LIMIT,
};
/* SB-RMI registers */
enum sbrmi_reg {
SBRMI_CTRL = 0x01,
SBRMI_STATUS,
SBRMI_OUTBNDMSG0 = 0x30,
SBRMI_OUTBNDMSG1,
SBRMI_OUTBNDMSG2,
SBRMI_OUTBNDMSG3,
SBRMI_OUTBNDMSG4,
SBRMI_OUTBNDMSG5,
SBRMI_OUTBNDMSG6,
SBRMI_OUTBNDMSG7,
SBRMI_INBNDMSG0,
SBRMI_INBNDMSG1,
SBRMI_INBNDMSG2,
SBRMI_INBNDMSG3,
SBRMI_INBNDMSG4,
SBRMI_INBNDMSG5,
SBRMI_INBNDMSG6,
SBRMI_INBNDMSG7,
SBRMI_SW_INTERRUPT,
};
/* Each client has this additional data */
struct sbrmi_data {
struct i2c_client *client;
struct mutex lock;
u32 pwr_limit_max;
};
struct sbrmi_mailbox_msg {
u8 cmd;
bool read;
u32 data_in;
u32 data_out;
};
static int sbrmi_enable_alert(struct i2c_client *client)
{
int ctrl;
/*
* Enable the SB-RMI Software alert status
* by writing 0 to bit 4 of Control register(0x1)
*/
ctrl = i2c_smbus_read_byte_data(client, SBRMI_CTRL);
if (ctrl < 0)
return ctrl;
if (ctrl & 0x10) {
ctrl &= ~0x10;
return i2c_smbus_write_byte_data(client,
SBRMI_CTRL, ctrl);
}
return 0;
}
static int rmi_mailbox_xfer(struct sbrmi_data *data,
struct sbrmi_mailbox_msg *msg)
{
int i, ret, retry = 10;
int sw_status;
u8 byte;
mutex_lock(&data->lock);
/* Indicate firmware a command is to be serviced */
ret = i2c_smbus_write_byte_data(data->client,
SBRMI_INBNDMSG7, START_CMD);
if (ret < 0)
goto exit_unlock;
/* Write the command to SBRMI::InBndMsg_inst0 */
ret = i2c_smbus_write_byte_data(data->client,
SBRMI_INBNDMSG0, msg->cmd);
if (ret < 0)
goto exit_unlock;
/*
* For both read and write the initiator (BMC) writes
* Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1]
* SBRMI_x3C(MSB):SBRMI_x39(LSB)
*/
for (i = 0; i < 4; i++) {
byte = (msg->data_in >> i * 8) & 0xff;
ret = i2c_smbus_write_byte_data(data->client,
SBRMI_INBNDMSG1 + i, byte);
if (ret < 0)
goto exit_unlock;
}
/*
* Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to
* perform the requested read or write command
*/
ret = i2c_smbus_write_byte_data(data->client,
SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX);
if (ret < 0)
goto exit_unlock;
/*
* Firmware will write SBRMI::Status[SwAlertSts]=1 to generate
* an ALERT (if enabled) to initiator (BMC) to indicate completion
* of the requested command
*/
do {
sw_status = i2c_smbus_read_byte_data(data->client,
SBRMI_STATUS);
if (sw_status < 0) {
ret = sw_status;
goto exit_unlock;
}
if (sw_status & SW_ALERT_MASK)
break;
usleep_range(50, 100);
} while (retry--);
if (retry < 0) {
dev_err(&data->client->dev,
"Firmware fail to indicate command completion\n");
ret = -EIO;
goto exit_unlock;
}
/*
* For a read operation, the initiator (BMC) reads the firmware
* response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1]
* {SBRMI_x34(MSB):SBRMI_x31(LSB)}.
*/
if (msg->read) {
for (i = 0; i < 4; i++) {
ret = i2c_smbus_read_byte_data(data->client,
SBRMI_OUTBNDMSG1 + i);
if (ret < 0)
goto exit_unlock;
msg->data_out |= ret << i * 8;
}
}
/*
* BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the
* ALERT to initiator
*/
ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS,
sw_status | SW_ALERT_MASK);
exit_unlock:
mutex_unlock(&data->lock);
return ret;
}
static int sbrmi_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct sbrmi_data *data = dev_get_drvdata(dev);
struct sbrmi_mailbox_msg msg = { 0 };
int ret;
if (type != hwmon_power)
return -EINVAL;
msg.read = true;
switch (attr) {
case hwmon_power_input:
msg.cmd = SBRMI_READ_PKG_PWR_CONSUMPTION;
ret = rmi_mailbox_xfer(data, &msg);
break;
case hwmon_power_cap:
msg.cmd = SBRMI_READ_PKG_PWR_LIMIT;
ret = rmi_mailbox_xfer(data, &msg);
break;
case hwmon_power_cap_max:
msg.data_out = data->pwr_limit_max;
ret = 0;
break;
default:
return -EINVAL;
}
if (ret < 0)
return ret;
/* hwmon power attributes are in microWatt */
*val = (long)msg.data_out * 1000;
return ret;
}
static int sbrmi_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct sbrmi_data *data = dev_get_drvdata(dev);
struct sbrmi_mailbox_msg msg = { 0 };
if (type != hwmon_power && attr != hwmon_power_cap)
return -EINVAL;
/*
* hwmon power attributes are in microWatt
* mailbox read/write is in mWatt
*/
val /= 1000;
val = clamp_val(val, SBRMI_PWR_MIN, data->pwr_limit_max);
msg.cmd = SBRMI_WRITE_PKG_PWR_LIMIT;
msg.data_in = val;
msg.read = false;
return rmi_mailbox_xfer(data, &msg);
}
static umode_t sbrmi_is_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
switch (type) {
case hwmon_power:
switch (attr) {
case hwmon_power_input:
case hwmon_power_cap_max:
return 0444;
case hwmon_power_cap:
return 0644;
}
break;
default:
break;
}
return 0;
}
static const struct hwmon_channel_info * const sbrmi_info[] = {
HWMON_CHANNEL_INFO(power,
HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX),
NULL
};
static const struct hwmon_ops sbrmi_hwmon_ops = {
.is_visible = sbrmi_is_visible,
.read = sbrmi_read,
.write = sbrmi_write,
};
static const struct hwmon_chip_info sbrmi_chip_info = {
.ops = &sbrmi_hwmon_ops,
.info = sbrmi_info,
};
static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data)
{
struct sbrmi_mailbox_msg msg = { 0 };
int ret;
msg.cmd = SBRMI_READ_PKG_MAX_PWR_LIMIT;
msg.read = true;
ret = rmi_mailbox_xfer(data, &msg);
if (ret < 0)
return ret;
data->pwr_limit_max = msg.data_out;
return ret;
}
static int sbrmi_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device *hwmon_dev;
struct sbrmi_data *data;
int ret;
data = devm_kzalloc(dev, sizeof(struct sbrmi_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->client = client;
mutex_init(&data->lock);
/* Enable alert for SB-RMI sequence */
ret = sbrmi_enable_alert(client);
if (ret < 0)
return ret;
/* Cache maximum power limit */
ret = sbrmi_get_max_pwr_limit(data);
if (ret < 0)
return ret;
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
&sbrmi_chip_info, NULL);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id sbrmi_id[] = {
{"sbrmi"},
{}
};
MODULE_DEVICE_TABLE(i2c, sbrmi_id);
static const struct of_device_id __maybe_unused sbrmi_of_match[] = {
{
.compatible = "amd,sbrmi",
},
{ },
};
MODULE_DEVICE_TABLE(of, sbrmi_of_match);
static struct i2c_driver sbrmi_driver = {
.driver = {
.name = "sbrmi",
.of_match_table = of_match_ptr(sbrmi_of_match),
},
.probe = sbrmi_probe,
.id_table = sbrmi_id,
};
module_i2c_driver(sbrmi_driver);
MODULE_AUTHOR("Akshay Gupta <akshay.gupta@amd.com>");
MODULE_DESCRIPTION("Hwmon driver for AMD SB-RMI emulated sensor");
MODULE_LICENSE("GPL");

View file

@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
To compile this driver as a module, choose M here: the module will be
called coresight-dummy.
config CORESIGHT_KUNIT_TESTS
tristate "Enable Coresight unit tests"
depends on KUNIT
default KUNIT_ALL_TESTS
help
Enable Coresight unit tests. Only useful for development and not
intended for production.
endif

View file

@ -22,6 +22,8 @@ condflags := \
$(call cc-option, -Wstringop-truncation)
subdir-ccflags-y += $(condflags)
CFLAGS_coresight-stm.o := -D__DISABLE_TRACE_MMIO__
obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
coresight-sysfs.o coresight-syscfg.o coresight-config.o \
@ -53,3 +55,4 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
coresight-ctcu-y := coresight-ctcu-core.o
obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o

View file

@ -113,8 +113,7 @@ typedef u64 cate_t;
* containing the data page pointer for @offset. If @daddrp is not NULL,
* @daddrp points the DMA address of the beginning of the table.
*/
static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
unsigned long offset,
static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
dma_addr_t *daddrp)
{
unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
}
#else
static inline void catu_dump_table(struct tmc_sg_table *catu_table)
static void catu_dump_table(struct tmc_sg_table *catu_table)
{
}
#endif
static inline cate_t catu_make_entry(dma_addr_t addr)
static cate_t catu_make_entry(dma_addr_t addr)
{
return addr ? CATU_VALID_ENTRY(addr) : 0;
}
@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
};
static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
static int catu_wait_for_ready(struct catu_drvdata *drvdata)
{
struct csdev_access *csa = &drvdata->csdev->access;
@ -458,12 +457,17 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
void *data)
{
int rc;
int rc = 0;
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
if (csdev->refcnt == 0) {
CS_UNLOCK(catu_drvdata->base);
rc = catu_enable_hw(catu_drvdata, mode, data);
CS_LOCK(catu_drvdata->base);
}
if (!rc)
csdev->refcnt++;
return rc;
}
@ -486,12 +490,15 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
static int catu_disable(struct coresight_device *csdev, void *__unused)
{
int rc;
int rc = 0;
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
if (--csdev->refcnt == 0) {
CS_UNLOCK(catu_drvdata->base);
rc = catu_disable_hw(catu_drvdata);
CS_LOCK(catu_drvdata->base);
}
return rc;
}
@ -550,6 +557,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
dev->platform_data = pdata;
drvdata->base = base;
raw_spin_lock_init(&drvdata->spinlock);
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
catu_desc.pdata = pdata;
catu_desc.dev = dev;
@ -558,6 +566,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
catu_desc.ops = &catu_ops;
coresight_clear_self_claim_tag(&catu_desc.access);
drvdata->csdev = coresight_register(&catu_desc);
if (IS_ERR(drvdata->csdev))
ret = PTR_ERR(drvdata->csdev);
@ -702,7 +711,7 @@ static int __init catu_init(void)
{
int ret;
ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);
ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver, THIS_MODULE);
tmc_etr_set_catu_ops(&etr_catu_buf_ops);
return ret;
}

View file

@ -65,6 +65,7 @@ struct catu_drvdata {
void __iomem *base;
struct coresight_device *csdev;
int irq;
raw_spinlock_t spinlock;
};
#define CATU_REG32(name, offset) \

View file

@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
* @feats_csdev:references to the device features to enable.
*/
struct cscfg_config_csdev {
const struct cscfg_config_desc *config_desc;
struct cscfg_config_desc *config_desc;
struct coresight_device *csdev;
bool enabled;
struct list_head node;

View file

@ -129,34 +129,36 @@ coresight_find_out_connection(struct coresight_device *csdev,
return ERR_PTR(-ENODEV);
}
static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
static u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
{
return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
return FIELD_GET(CORESIGHT_CLAIM_MASK,
csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
}
static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
{
return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
}
static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
{
return coresight_read_claim_tags(csdev) != 0;
}
static inline void coresight_set_claim_tags(struct coresight_device *csdev)
static void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
{
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMSET);
isb();
}
static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
void coresight_clear_self_claim_tag(struct csdev_access *csa)
{
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
if (csa->io_mem)
CS_UNLOCK(csa->base);
coresight_clear_self_claim_tag_unlocked(csa);
if (csa->io_mem)
CS_LOCK(csa->base);
}
EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
{
csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMCLR);
isb();
}
EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
/*
* coresight_claim_device_unlocked : Claim the device for self-hosted usage
@ -170,18 +172,41 @@ static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
*/
int coresight_claim_device_unlocked(struct coresight_device *csdev)
{
int tag;
struct csdev_access *csa;
if (WARN_ON(!csdev))
return -EINVAL;
if (coresight_is_claimed_any(csdev))
csa = &csdev->access;
tag = coresight_read_claim_tags_unlocked(csdev);
switch (tag) {
case CORESIGHT_CLAIM_FREE:
coresight_set_self_claim_tag_unlocked(csdev);
if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
return 0;
/* There was a race setting the tag, clean up and fail */
coresight_clear_self_claim_tag_unlocked(csa);
dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
return -EBUSY;
coresight_set_claim_tags(csdev);
if (coresight_is_claimed_self_hosted(csdev))
return 0;
/* There was a race setting the tags, clean up and fail */
coresight_clear_claim_tags(csdev);
case CORESIGHT_CLAIM_EXTERNAL:
/* External debug is an expected state, so log and report BUSY */
dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
return -EBUSY;
default:
case CORESIGHT_CLAIM_SELF_HOSTED:
case CORESIGHT_CLAIM_INVALID:
/*
* Warn here because we clear a lingering self hosted tag
* on probe, so other tag combinations are impossible.
*/
dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
return -EBUSY;
}
}
EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
@ -201,7 +226,7 @@ int coresight_claim_device(struct coresight_device *csdev)
EXPORT_SYMBOL_GPL(coresight_claim_device);
/*
* coresight_disclaim_device_unlocked : Clear the claim tags for the device.
* coresight_disclaim_device_unlocked : Clear the claim tag for the device.
* Called with CS_UNLOCKed for the component.
*/
void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
@ -210,15 +235,15 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
if (WARN_ON(!csdev))
return;
if (coresight_is_claimed_self_hosted(csdev))
coresight_clear_claim_tags(csdev);
if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
coresight_clear_self_claim_tag_unlocked(&csdev->access);
else
/*
* The external agent may have not honoured our claim
* and has manipulated it. Or something else has seriously
* gone wrong in our driver.
*/
WARN_ON_ONCE(1);
dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
@ -367,6 +392,28 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
}
EXPORT_SYMBOL_GPL(coresight_disable_source);
void coresight_pause_source(struct coresight_device *csdev)
{
if (!coresight_is_percpu_source(csdev))
return;
if (source_ops(csdev)->pause_perf)
source_ops(csdev)->pause_perf(csdev);
}
EXPORT_SYMBOL_GPL(coresight_pause_source);
int coresight_resume_source(struct coresight_device *csdev)
{
if (!coresight_is_percpu_source(csdev))
return -EOPNOTSUPP;
if (!source_ops(csdev)->resume_perf)
return -EOPNOTSUPP;
return source_ops(csdev)->resume_perf(csdev);
}
EXPORT_SYMBOL_GPL(coresight_resume_source);
/*
* coresight_disable_path_from : Disable components in the given path beyond
* @nd in the list. If @nd is NULL, all the components, except the SOURCE are
@ -465,7 +512,7 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
/* Enable all helpers adjacent to the path first */
ret = coresight_enable_helpers(csdev, mode, path);
if (ret)
goto err;
goto err_disable_path;
/*
* ETF devices are tricky... They can be a link or a sink,
* depending on how they are configured. If an ETF has been
@ -486,8 +533,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
* that need disabling. Disabling the path here
* would mean we could disrupt an existing session.
*/
if (ret)
if (ret) {
coresight_disable_helpers(csdev, path);
goto out;
}
break;
case CORESIGHT_DEV_TYPE_SOURCE:
/* sources are enabled from either sysFS or Perf */
@ -497,16 +546,19 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
child = list_next_entry(nd, link)->csdev;
ret = coresight_enable_link(csdev, parent, child, source);
if (ret)
goto err;
goto err_disable_helpers;
break;
default:
goto err;
ret = -EINVAL;
goto err_disable_helpers;
}
}
out:
return ret;
err:
err_disable_helpers:
coresight_disable_helpers(csdev, path);
err_disable_path:
coresight_disable_path_from(path, nd);
goto out;
}
@ -579,7 +631,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
* Return true in successful case and power up the device.
* Return false when failed to get reference of module.
*/
static inline bool coresight_get_ref(struct coresight_device *csdev)
static bool coresight_get_ref(struct coresight_device *csdev)
{
struct device *dev = csdev->dev.parent;
@ -598,7 +650,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
*
* @csdev: The coresight device to decrement a reference from.
*/
static inline void coresight_put_ref(struct coresight_device *csdev)
static void coresight_put_ref(struct coresight_device *csdev)
{
struct device *dev = csdev->dev.parent;
@ -821,7 +873,7 @@ void coresight_release_path(struct coresight_path *path)
}
/* return true if the device is a suitable type for a default sink */
static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
static bool coresight_is_def_sink_type(struct coresight_device *csdev)
{
/* sink & correct subtype */
if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
@ -959,6 +1011,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
}
return csdev->def_sink;
}
EXPORT_SYMBOL_GPL(coresight_find_default_sink);
static int coresight_remove_sink_ref(struct device *dev, void *data)
{
@ -1385,7 +1438,7 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
*
* Returns the index of the entry, when found. Otherwise, -ENOENT.
*/
static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
static int coresight_search_device_idx(struct coresight_dev_list *dict,
struct fwnode_handle *fwnode)
{
int i;
@ -1585,17 +1638,17 @@ module_init(coresight_init);
module_exit(coresight_exit);
int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
struct platform_driver *pdev_drv)
struct platform_driver *pdev_drv, struct module *owner)
{
int ret;
ret = amba_driver_register(amba_drv);
ret = __amba_driver_register(amba_drv, owner);
if (ret) {
pr_err("%s: error registering AMBA driver\n", drv);
return ret;
}
ret = platform_driver_register(pdev_drv);
ret = __platform_driver_register(pdev_drv, owner);
if (!ret)
return 0;

View file

@ -774,7 +774,8 @@ static struct platform_driver debug_platform_driver = {
static int __init debug_init(void)
{
return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
return coresight_init_driver("debug", &debug_driver, &debug_platform_driver,
THIS_MODULE);
}
static void __exit debug_exit(void)

View file

@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
cti_desc.ops = &cti_ops;
cti_desc.groups = drvdata->ctidev.con_groups;
cti_desc.dev = dev;
coresight_clear_self_claim_tag(&cti_desc.access);
drvdata->csdev = coresight_register(&cti_desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);

View file

@ -9,7 +9,6 @@
#include <linux/coresight.h>
#include <linux/device.h>
#include <linux/fwnode.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/sysfs.h>
@ -17,6 +16,8 @@
#include "coresight-priv.h"
struct fwnode_handle;
/*
* Device registers
* 0x000 - 0x144: CTI programming and status

View file

@ -95,7 +95,7 @@ struct etb_drvdata {
static int etb_set_buffer(struct coresight_device *csdev,
struct perf_output_handle *handle);
static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
{
return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
}
@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
desc.pdata = pdata;
desc.dev = dev;
desc.groups = coresight_etb_groups;
coresight_clear_self_claim_tag(&desc.access);
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);

View file

@ -365,6 +365,18 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
continue;
}
/*
* If AUX pause feature is enabled but the ETM driver does not
* support the operations, clear this CPU from the mask and
* continue to next one.
*/
if (event->attr.aux_start_paused &&
(!source_ops(csdev)->pause_perf || !source_ops(csdev)->resume_perf)) {
dev_err_once(&csdev->dev, "AUX pause is not supported.\n");
cpumask_clear_cpu(cpu, mask);
continue;
}
/*
* No sink provided - look for a default sink for all the ETMs,
* where this event can be scheduled.
@ -450,6 +462,15 @@ err:
goto out;
}
static int etm_event_resume(struct coresight_device *csdev,
struct etm_ctxt *ctxt)
{
if (!ctxt->event_data)
return 0;
return coresight_resume_source(csdev);
}
static void etm_event_start(struct perf_event *event, int flags)
{
int cpu = smp_processor_id();
@ -463,6 +484,14 @@ static void etm_event_start(struct perf_event *event, int flags)
if (!csdev)
goto fail;
if (flags & PERF_EF_RESUME) {
if (etm_event_resume(csdev, ctxt) < 0) {
dev_err(&csdev->dev, "Failed to resume ETM event.\n");
goto fail;
}
return;
}
/* Have we messed up our tracking ? */
if (WARN_ON(ctxt->event_data))
goto fail;
@ -545,6 +574,55 @@ fail:
return;
}
static void etm_event_pause(struct perf_event *event,
struct coresight_device *csdev,
struct etm_ctxt *ctxt)
{
int cpu = smp_processor_id();
struct coresight_device *sink;
struct perf_output_handle *handle = &ctxt->handle;
struct coresight_path *path;
unsigned long size;
if (!ctxt->event_data)
return;
/* Stop tracer */
coresight_pause_source(csdev);
path = etm_event_cpu_path(ctxt->event_data, cpu);
sink = coresight_get_sink(path);
if (WARN_ON_ONCE(!sink))
return;
/*
* The per CPU sink has own interrupt handling, it might have
* race condition with updating buffer on AUX trace pause if
* it is invoked from NMI. To avoid the race condition,
* disallows updating buffer for the per CPU sink case.
*/
if (coresight_is_percpu_sink(sink))
return;
if (WARN_ON_ONCE(handle->event != event))
return;
if (!sink_ops(sink)->update_buffer)
return;
size = sink_ops(sink)->update_buffer(sink, handle,
ctxt->event_data->snk_config);
if (READ_ONCE(handle->event)) {
if (!size)
return;
perf_aux_output_end(handle, size);
perf_aux_output_begin(handle, event);
} else {
WARN_ON_ONCE(size);
}
}
static void etm_event_stop(struct perf_event *event, int mode)
{
int cpu = smp_processor_id();
@ -555,6 +633,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
struct etm_event_data *event_data;
struct coresight_path *path;
if (mode & PERF_EF_PAUSE)
return etm_event_pause(event, csdev, ctxt);
/*
* If we still have access to the event_data via handle,
* confirm that we haven't messed up the tracking.
@ -899,7 +980,8 @@ int __init etm_perf_init(void)
int ret;
etm_pmu.capabilities = (PERF_PMU_CAP_EXCLUSIVE |
PERF_PMU_CAP_ITRACE);
PERF_PMU_CAP_ITRACE |
PERF_PMU_CAP_AUX_PAUSE);
etm_pmu.attr_groups = etm_pmu_attr_groups;
etm_pmu.task_ctx_nr = perf_sw_context;

View file

@ -229,7 +229,7 @@ struct etm_config {
* @config: structure holding configuration parameters.
*/
struct etm_drvdata {
void __iomem *base;
struct csdev_access csa;
struct clk *atclk;
struct coresight_device *csdev;
spinlock_t spinlock;
@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
"invalid CP14 access to ETM reg: %#x", off);
}
} else {
writel_relaxed(val, drvdata->base + off);
writel_relaxed(val, drvdata->csa.base + off);
}
}
@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
"invalid CP14 access to ETM reg: %#x", off);
}
} else {
val = readl_relaxed(drvdata->base + off);
val = readl_relaxed(drvdata->csa.base + off);
}
return val;

View file

@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
{
u32 etmpdcr;
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
etmpdcr |= ETMPDCR_PWD_UP;
writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
/* Ensure pwrup completes before subsequent cp14 accesses */
mb();
isb();
@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
/* Ensure pending cp14 accesses complete before clearing pwrup */
mb();
isb();
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
etmpdcr &= ~ETMPDCR_PWD_UP;
writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
}
/**
@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
rc = coresight_claim_device_unlocked(csdev);
if (rc)
@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
etm_clr_prog(drvdata);
done:
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
drvdata->cpu, rc);
@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
etm_set_prog(drvdata);
/* Read back sequencer and counters for post trace analysis */
@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
dev_dbg(&drvdata->csdev->dev,
"cpu: %d disable smp call done\n", drvdata->cpu);
@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
return;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
/* Setting the prog bit disables tracing immediately */
etm_set_prog(drvdata);
@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
/*
* perf will release trace ids when _free_aux()
@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
/* Make sure all registers are accessible */
etm_os_unlock(drvdata);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
/* First dummy read */
(void)etm_readl(drvdata, ETMPDSR);
@ -764,9 +764,10 @@ static void etm_init_arch_data(void *info)
drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
etm_set_pwrdwn(drvdata);
etm_clr_pwrup(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
}
static int __init etm_hp_setup(void)
@ -827,8 +828,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);

View file

@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
pm_runtime_get_sync(dev->parent);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
val = etm_readl(drvdata, ETMSR);
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
pm_runtime_put(dev->parent);
@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
pm_runtime_get_sync(dev->parent);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(drvdata->csa.base);
val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
CS_LOCK(drvdata->base);
CS_LOCK(drvdata->csa.base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
pm_runtime_put(dev->parent);

View file

@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
* TRCIDR4.NUMPC > 0b0000 .
* TRCSSCSR<n>.PC == 0b1
*/
static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
{
return (n < drvdata->nr_ss_cmp) &&
drvdata->nr_pe &&
@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
isb();
}
static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
{
WARN_ON(drvdata->cpu != smp_processor_id());
@ -431,6 +431,44 @@ static int etm4x_wait_status(struct csdev_access *csa, int pos, int val)
return coresight_timeout(csa, TRCSTATR, pos, val);
}
static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
struct device *etm_dev = &csdev->dev;
struct csdev_access *csa = &csdev->access;
/*
* ETE mandates that the TRCRSR is written to before
* enabling it.
*/
if (etm4x_is_ete(drvdata))
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
etm4x_allow_trace(drvdata);
/* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
/* Synchronize the register updates for sysreg access */
if (!csa->io_mem)
isb();
/* wait for TRCSTATR.IDLE to go back down to '0' */
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) {
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
return -ETIME;
}
/*
* As recommended by section 4.3.7 ("Synchronization when using the
* memory-mapped interface") of ARM IHI 0064D
*/
dsb(sy);
isb();
return 0;
}
static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
{
int i, rc;
@ -539,33 +577,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
}
/*
* ETE mandates that the TRCRSR is written to before
* enabling it.
*/
if (etm4x_is_ete(drvdata))
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
etm4x_allow_trace(drvdata);
/* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
/* Synchronize the register updates for sysreg access */
if (!csa->io_mem)
isb();
/* wait for TRCSTATR.IDLE to go back down to '0' */
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
/*
* As recommended by section 4.3.7 ("Synchronization when using the
* memory-mapped interface") of ARM IHI 0064D
*/
dsb(sy);
isb();
if (!drvdata->paused)
rc = etm4_enable_trace_unit(drvdata);
done:
etm4_cs_lock(drvdata, csa);
@ -808,6 +821,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
drvdata->trcid = path->trace_id;
/* Populate pause state */
drvdata->paused = !!READ_ONCE(event->hw.aux_paused);
/* And enable it */
ret = etm4_enable_hw(drvdata);
@ -834,6 +850,9 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
drvdata->trcid = path->trace_id;
/* Tracer will never be paused in sysfs mode */
drvdata->paused = false;
/*
* Executing etm4_enable_hw on the cpu whose ETM is being enabled
* ensures that register writes occur when cpu is powered.
@ -884,25 +903,12 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
return ret;
}
static void etm4_disable_hw(void *info)
static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
{
u32 control;
struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
struct device *etm_dev = &csdev->dev;
struct csdev_access *csa = &csdev->access;
int i;
etm4_cs_unlock(drvdata, csa);
etm4_disable_arch_specific(drvdata);
if (!drvdata->skip_power_up) {
/* power can be removed from the trace unit now */
control = etm4x_relaxed_read32(csa, TRCPDCR);
control &= ~TRCPDCR_PU;
etm4x_relaxed_write32(csa, control, TRCPDCR);
}
control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
@ -943,6 +949,28 @@ static void etm4_disable_hw(void *info)
* of ARM IHI 0064H.b.
*/
isb();
}
static void etm4_disable_hw(void *info)
{
u32 control;
struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
int i;
etm4_cs_unlock(drvdata, csa);
etm4_disable_arch_specific(drvdata);
if (!drvdata->skip_power_up) {
/* power can be removed from the trace unit now */
control = etm4x_relaxed_read32(csa, TRCPDCR);
control &= ~TRCPDCR_PU;
etm4x_relaxed_write32(csa, control, TRCPDCR);
}
etm4_disable_trace_unit(drvdata);
/* read the status of the single shot comparators */
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
@ -1020,6 +1048,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
raw_spin_unlock(&drvdata->spinlock);
cscfg_csdev_disable_active_config(csdev);
cpus_read_unlock();
/*
@ -1059,10 +1090,43 @@ static void etm4_disable(struct coresight_device *csdev,
coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static int etm4_resume_perf(struct coresight_device *csdev)
{
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &csdev->access;
if (coresight_get_mode(csdev) != CS_MODE_PERF)
return -EINVAL;
etm4_cs_unlock(drvdata, csa);
etm4_enable_trace_unit(drvdata);
etm4_cs_lock(drvdata, csa);
drvdata->paused = false;
return 0;
}
static void etm4_pause_perf(struct coresight_device *csdev)
{
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &csdev->access;
if (coresight_get_mode(csdev) != CS_MODE_PERF)
return;
etm4_cs_unlock(drvdata, csa);
etm4_disable_trace_unit(drvdata);
etm4_cs_lock(drvdata, csa);
drvdata->paused = true;
}
static const struct coresight_ops_source etm4_source_ops = {
.cpu_id = etm4_cpu_id,
.enable = etm4_enable,
.disable = etm4_disable,
.resume_perf = etm4_resume_perf,
.pause_perf = etm4_pause_perf,
};
static const struct coresight_ops etm4_cs_ops = {
@ -1070,7 +1134,7 @@ static const struct coresight_ops etm4_cs_ops = {
.source_ops = &etm4_source_ops,
};
static inline bool cpu_supports_sysreg_trace(void)
static bool cpu_supports_sysreg_trace(void)
{
u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
@ -1176,7 +1240,7 @@ static void cpu_detect_trace_filtering(struct etmv4_drvdata *drvdata)
* tracing at the kernel EL and EL0, forcing to use the
* virtual time as the timestamp.
*/
trfcr = (TRFCR_EL1_TS_VIRTUAL |
trfcr = (FIELD_PREP(TRFCR_EL1_TS_MASK, TRFCR_EL1_TS_VIRTUAL) |
TRFCR_EL1_ExTRE |
TRFCR_EL1_E0TRE);
@ -1372,11 +1436,13 @@ static void etm4_init_arch_data(void *info)
drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
/* NUMCNTR, bits[30:28] number of counters available for tracing */
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
coresight_clear_self_claim_tag_unlocked(csa);
etm4_cs_lock(drvdata, csa);
cpu_detect_trace_filtering(drvdata);
}
static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
{
return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
}

View file

@ -2320,11 +2320,11 @@ static ssize_t ts_source_show(struct device *dev,
goto out;
}
switch (drvdata->trfcr & TRFCR_EL1_TS_MASK) {
val = FIELD_GET(TRFCR_EL1_TS_MASK, drvdata->trfcr);
switch (val) {
case TRFCR_EL1_TS_VIRTUAL:
case TRFCR_EL1_TS_GUEST_PHYSICAL:
case TRFCR_EL1_TS_PHYSICAL:
val = FIELD_GET(TRFCR_EL1_TS_MASK, drvdata->trfcr);
break;
default:
val = -1;
@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
return reg.data;
}
static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
{
struct dev_ext_attribute *eattr;
@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
}
static inline bool
static bool
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
{
switch (offset) {

View file

@ -983,6 +983,7 @@ struct etmv4_save_state {
* @state_needs_restore: True when there is context to restore after PM exit
* @skip_power_up: Indicates if an implementation can skip powering up
* the trace unit.
* @paused: Indicates if the trace unit is paused.
* @arch_features: Bitmap of arch features of etmv4 devices.
*/
struct etmv4_drvdata {
@ -1036,6 +1037,7 @@ struct etmv4_drvdata {
struct etmv4_save_state *save_state;
bool state_needs_restore;
bool skip_power_up;
bool paused;
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
};

View file

@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
drvdata->base = base;
desc.groups = coresight_funnel_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
coresight_clear_self_claim_tag(&desc.access);
}
dev_set_drvdata(dev, drvdata);
@ -433,7 +434,8 @@ static struct amba_driver dynamic_funnel_driver = {
static int __init funnel_init(void)
{
return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver,
THIS_MODULE);
}
static void __exit funnel_exit(void)

View file

@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0
#include <kunit/test.h>
#include <kunit/device.h>
#include <linux/coresight.h>
#include "coresight-priv.h"
static struct coresight_device *coresight_test_device(struct device *dev)
{
struct coresight_device *csdev = devm_kcalloc(dev, 1,
sizeof(struct coresight_device),
GFP_KERNEL);
csdev->pdata = devm_kcalloc(dev, 1,
sizeof(struct coresight_platform_data),
GFP_KERNEL);
return csdev;
}
static void test_default_sink(struct kunit *test)
{
/*
* Source -> ETF -> ETR -> CATU
* ^
* | default
*/
struct device *dev = kunit_device_register(test, "coresight_kunit");
struct coresight_device *src = coresight_test_device(dev),
*etf = coresight_test_device(dev),
*etr = coresight_test_device(dev),
*catu = coresight_test_device(dev);
struct coresight_connection conn = {};
src->type = CORESIGHT_DEV_TYPE_SOURCE;
/*
* Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
* a TRBE sink if one is registered.
*/
src->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
etr->type = CORESIGHT_DEV_TYPE_SINK;
etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
catu->type = CORESIGHT_DEV_TYPE_HELPER;
conn.src_dev = src;
conn.dest_dev = etf;
coresight_add_out_conn(dev, src->pdata, &conn);
conn.src_dev = etf;
conn.dest_dev = etr;
coresight_add_out_conn(dev, etf->pdata, &conn);
conn.src_dev = etr;
conn.dest_dev = catu;
coresight_add_out_conn(dev, etr->pdata, &conn);
KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(src), etr);
}
static struct kunit_case coresight_testcases[] = {
KUNIT_CASE(test_default_sink),
{}
};
static struct kunit_suite coresight_test_suite = {
.name = "coresight_test_suite",
.test_cases = coresight_testcases,
};
kunit_test_suites(&coresight_test_suite);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Clark <james.clark@linaro.org>");
MODULE_DESCRIPTION("Arm CoreSight KUnit tests");

View file

@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
#ifdef CONFIG_OF
static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
{
return of_property_read_bool(ep, "slave-mode");
}
@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
return parent;
}
static inline struct device_node *
static struct device_node *
of_coresight_get_output_ports_node(const struct device_node *node)
{
return of_get_child_by_name(node, "out-ports");
@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
return 0;
}
#else
static inline int
static int
of_get_coresight_platform_data(struct device *dev,
struct coresight_platform_data *pdata)
{
return -ENOENT;
}
static inline int of_coresight_get_cpu(struct device *dev)
static int of_coresight_get_cpu(struct device *dev)
{
return -ENODEV;
}
@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
#define ACPI_CORESIGHT_LINK_SLAVE 0
#define ACPI_CORESIGHT_LINK_MASTER 1
static inline bool is_acpi_guid(const union acpi_object *obj)
static bool is_acpi_guid(const union acpi_object *obj)
{
return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
}
@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
* acpi_guid_matches - Checks if the given object is a GUID object and
* that it matches the supplied the GUID.
*/
static inline bool acpi_guid_matches(const union acpi_object *obj,
static bool acpi_guid_matches(const union acpi_object *obj,
const guid_t *guid)
{
return is_acpi_guid(obj) &&
guid_equal((guid_t *)obj->buffer.pointer, guid);
}
static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
{
return acpi_guid_matches(obj, &acpi_graph_uuid);
}
static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
{
return acpi_guid_matches(obj, &coresight_graph_uuid);
}
static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
static bool is_acpi_coresight_graph(const union acpi_object *obj)
{
const union acpi_object *graphid, *guid, *links;
@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
* }, // End of ACPI Graph Property
* })
*/
static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
static bool acpi_validate_dsd_graph(const union acpi_object *graph)
{
int i, n;
const union acpi_object *rev, *nr_graphs;
@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
return NULL;
}
static inline bool
static bool
acpi_validate_coresight_graph(const union acpi_object *cs_graph)
{
int nlinks;
@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
#else
static inline int
static int
acpi_get_coresight_platform_data(struct device *dev,
struct coresight_platform_data *pdata)
{
return -ENOENT;
}
static inline int acpi_coresight_get_cpu(struct device *dev)
static int acpi_coresight_get_cpu(struct device *dev)
{
return -ENODEV;
}

View file

@ -35,7 +35,11 @@ extern const struct device_type coresight_dev_type[];
* Coresight device CLAIM protocol.
* See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
*/
#define CORESIGHT_CLAIM_SELF_HOSTED BIT(1)
#define CORESIGHT_CLAIM_MASK GENMASK(1, 0)
#define CORESIGHT_CLAIM_FREE 0
#define CORESIGHT_CLAIM_EXTERNAL 1
#define CORESIGHT_CLAIM_SELF_HOSTED 2
#define CORESIGHT_CLAIM_INVALID 3
#define TIMEOUT_US 100
#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
@ -56,10 +60,8 @@ struct cs_off_attribute {
u32 off;
};
extern ssize_t coresight_simple_show32(struct device *_dev,
struct device_attribute *attr, char *buf);
extern ssize_t coresight_simple_show_pair(struct device *_dev,
struct device_attribute *attr, char *buf);
ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf);
#define coresight_simple_reg32(name, offset) \
(&((struct cs_off_attribute[]) { \
@ -156,8 +158,8 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
enum cs_mode mode);
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
extern int etm_readl_cp14(u32 off, unsigned int *val);
extern int etm_writel_cp14(u32 off, u32 val);
int etm_readl_cp14(u32 off, unsigned int *val);
int etm_writel_cp14(u32 off, u32 val);
#else
static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
@ -168,8 +170,8 @@ struct cti_assoc_op {
void (*remove)(struct coresight_device *csdev);
};
extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
extern void coresight_remove_cti_ops(void);
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
void coresight_remove_cti_ops(void);
/*
* Macros and inline functions to handle CoreSight UCI data and driver
@ -249,5 +251,7 @@ void coresight_add_helper(struct coresight_device *csdev,
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
struct coresight_device *coresight_get_percpu_sink(int cpu);
void coresight_disable_source(struct coresight_device *csdev, void *data);
void coresight_pause_source(struct coresight_device *csdev);
int coresight_resume_source(struct coresight_device *csdev);
#endif

View file

@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
/*
* replicator_reset : Reset the replicator configuration to sane values.
*/
static inline void replicator_reset(struct replicator_drvdata *drvdata)
static void replicator_reset(struct replicator_drvdata *drvdata)
{
if (drvdata->base)
dynamic_replicator_reset(drvdata);
@ -262,6 +262,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
drvdata->base = base;
desc.groups = replicator_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
coresight_clear_self_claim_tag(&desc.access);
}
if (fwnode_property_present(dev_fwnode(dev),
@ -438,7 +439,8 @@ static struct amba_driver dynamic_replicator_driver = {
static int __init replicator_init(void)
{
return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver);
return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver,
THIS_MODULE);
}
static void __exit replicator_exit(void)

View file

@ -301,7 +301,7 @@ static const struct coresight_ops stm_cs_ops = {
.source_ops = &stm_source_ops,
};
static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
static bool stm_addr_unaligned(const void *addr, u8 write_bytes)
{
return ((unsigned long)addr & (write_bytes - 1));
}
@ -685,7 +685,7 @@ static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)
return of_address_to_resource(np, index, res);
}
#else
static inline int of_stm_get_stimulus_area(struct device *dev,
static int of_stm_get_stimulus_area(struct device *dev,
struct resource *res)
{
return -ENOENT;
@ -729,7 +729,7 @@ static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)
return rc;
}
#else
static inline int acpi_stm_get_stimulus_area(struct device *dev,
static int acpi_stm_get_stimulus_area(struct device *dev,
struct resource *res)
{
return -ENOENT;
@ -1058,7 +1058,7 @@ static struct platform_driver stm_platform_driver = {
static int __init stm_init(void)
{
return coresight_init_driver("stm", &stm_driver, &stm_platform_driver);
return coresight_init_driver("stm", &stm_driver, &stm_platform_driver, THIS_MODULE);
}
static void __exit stm_exit(void)

View file

@ -10,7 +10,7 @@
#include "coresight-syscfg-configfs.h"
/* create a default ci_type. */
static inline struct config_item_type *cscfg_create_ci_type(void)
static struct config_item_type *cscfg_create_ci_type(void)
{
struct config_item_type *ci_type;

View file

@ -395,6 +395,8 @@ static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, voi
if (list_empty(&csdev->config_csdev_list))
return;
guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock);
list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
if (config_csdev->config_desc->load_owner == load_owner)
list_del(&config_csdev->node);
@ -867,6 +869,25 @@ unlock_exit:
}
EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc)
{
if (!atomic_fetch_inc(&config_desc->active_cnt)) {
/* must ensure that config cannot be unloaded in use */
if (unlikely(cscfg_owner_get(config_desc->load_owner))) {
atomic_dec(&config_desc->active_cnt);
return false;
}
}
return true;
}
static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
{
if (!atomic_dec_return(&config_desc->active_cnt))
cscfg_owner_put(config_desc->load_owner);
}
/*
* This activate configuration for either perf or sysfs. Perf can have multiple
* active configs, selected per event, sysfs is limited to one.
@ -890,22 +911,17 @@ static int _cscfg_activate_config(unsigned long cfg_hash)
if (config_desc->available == false)
return -EBUSY;
/* must ensure that config cannot be unloaded in use */
err = cscfg_owner_get(config_desc->load_owner);
if (err)
if (!cscfg_config_desc_get(config_desc)) {
err = -EINVAL;
break;
}
/*
* increment the global active count - control changes to
* active configurations
*/
atomic_inc(&cscfg_mgr->sys_active_cnt);
/*
* mark the descriptor as active so enable config on a
* device instance will use it
*/
atomic_inc(&config_desc->active_cnt);
err = 0;
dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
break;
@ -920,9 +936,8 @@ static void _cscfg_deactivate_config(unsigned long cfg_hash)
list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
atomic_dec(&config_desc->active_cnt);
atomic_dec(&cscfg_mgr->sys_active_cnt);
cscfg_owner_put(config_desc->load_owner);
cscfg_config_desc_put(config_desc);
dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
break;
}
@ -1047,7 +1062,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
unsigned long cfg_hash, int preset)
{
struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
const struct cscfg_config_desc *config_desc;
struct cscfg_config_desc *config_desc;
unsigned long flags;
int err = 0;
@ -1062,8 +1077,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
config_desc = config_csdev_item->config_desc;
if ((atomic_read(&config_desc->active_cnt)) &&
((unsigned long)config_desc->event_ea->var == cfg_hash)) {
if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
cscfg_config_desc_get(config_desc)) {
config_csdev_active = config_csdev_item;
csdev->active_cscfg_ctxt = (void *)config_csdev_active;
break;
@ -1097,7 +1112,11 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
err = -EBUSY;
raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
}
if (err)
cscfg_config_desc_put(config_desc);
}
return err;
}
EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
@ -1136,8 +1155,10 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
/* true if there was an enabled active config */
if (config_csdev)
if (config_csdev) {
cscfg_csdev_disable_config(config_csdev);
cscfg_config_desc_put(config_csdev->config_desc);
}
}
EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);

Some files were not shown because too many files have changed in this diff Show more