* [PATCH 2/2] dt-bindings: Drop incorrect usage of double '::'
From: Krzysztof Kozlowski @ 2026-06-22 10:16 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Peter Griffin, Alim Akhtar, Michael Turquette,
Stephen Boyd, Brian Masney, Sylwester Nawrocki, Chanwoo Choi,
Sam Protsenko, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Inki Dae, Seung-Woo Kim, Kyungmin Park,
Andi Shyti, Georgi Djakov, Lee Jones, Pavel Machek, Hans Verkuil,
Mauro Carvalho Chehab, Ulf Hansson, Peter Rosin, Vinod Koul,
Neil Armstrong, Linus Walleij, Geert Uytterhoeven, Magnus Damm,
Sebastian Reichel, Javier Martinez Canillas, Liam Girdwood,
Mark Brown, Greg Kroah-Hartman, Jiri Slaby, Srinivas Kandagatla,
Bartlomiej Zolnierkiewicz, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Jonathan Marek, Taniya Das, Robert Marko,
Christian Marangi, Stephan Gerhold, Adam Skladowski,
Sireesh Kodali, Barnabas Czeman, Imran Shaik,
Sricharan Ramabadhran, Anusha Rao, Luo Jie, Tomasz Figa,
Chanho Park, Sunyeal Hong, Shin Son, Krishna Manikandan,
Jacek Anaszewski, Jaehoon Chung, Marek Szyprowski, Alina Yu,
Andy Gross, Niklas Söderlund, Wesley Cheng, linux-arm-msm,
devicetree, linux-kernel, linux-arm-kernel, linux-samsung-soc,
linux-clk, dri-devel, freedreno, linux-i2c, linux-pm, linux-leds,
linux-media, linux-mmc, linux-phy, linux-gpio, linux-renesas-soc,
linux-serial, linux-sound, linux-usb
Cc: Krzysztof Kozlowski
In-Reply-To: <20260622101606.485961-3-krzysztof.kozlowski@oss.qualcomm.com>
There is no use of double colon '::' in YAML. OTOH, the literal style
block, e.g. using '|' treats all characters as content [1] therefore
single use of ':' in descriptions is perfectly fine, whenever '|' is
used.
Cleanup existing code, so the confusing style won't be re-used in new
contributions.
Link: https://yaml.org/spec/1.2.2/#literal-style [1]
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Intention for this patch is to go via Rob's tree.
---
.../devicetree/bindings/arm/qcom-soc.yaml | 4 ++--
.../devicetree/bindings/arm/qcom.yaml | 4 ++--
.../bindings/arm/samsung/samsung-soc.yaml | 4 ++--
.../display/msm/dsi-controller-main.yaml | 20 +++++++++----------
.../display/samsung/samsung,fimd.yaml | 4 ++--
.../bindings/i2c/samsung,s3c2410-i2c.yaml | 2 +-
.../interconnect/qcom,msm8998-bwmon.yaml | 2 +-
.../interconnect/samsung,exynos-bus.yaml | 14 ++++++-------
.../bindings/leds/qcom,pm8058-led.yaml | 4 ++--
.../bindings/leds/skyworks,aat1290.yaml | 6 +++---
.../bindings/media/cec/cec-gpio.yaml | 2 +-
.../bindings/mmc/samsung,exynos-dw-mshc.yaml | 2 +-
.../devicetree/bindings/mux/mux-consumer.yaml | 4 ++--
.../bindings/phy/samsung,mipi-video-phy.yaml | 4 ++--
.../bindings/phy/samsung,usb2-phy.yaml | 2 +-
.../bindings/phy/samsung,usb3-drd-phy.yaml | 2 +-
.../bindings/pinctrl/samsung,pinctrl.yaml | 2 +-
.../bindings/power/renesas,rcar-sysc.yaml | 2 +-
.../bindings/power/reset/restart-handler.yaml | 8 ++++----
.../bindings/regulator/maxim,max77802.yaml | 4 ++--
.../bindings/regulator/richtek,rtq2208.yaml | 2 +-
.../bindings/serial/qcom,msm-uartdm.yaml | 2 +-
.../devicetree/bindings/slimbus/slimbus.yaml | 4 ++--
.../bindings/soc/qcom/qcom,apr-services.yaml | 2 +-
.../bindings/soc/qcom/qcom,rpmh-rsc.yaml | 8 ++++----
.../bindings/soc/qcom/qcom,wcnss.yaml | 2 +-
.../bindings/soc/renesas/renesas-soc.yaml | 4 ++--
.../bindings/sound/qcom,q6asm-dais.yaml | 2 +-
.../thermal/samsung,exynos-thermal.yaml | 4 ++--
.../devicetree/bindings/usb/qcom,dwc3.yaml | 12 +++++------
.../bindings/usb/qcom,snps-dwc3.yaml | 12 +++++------
31 files changed, 75 insertions(+), 75 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/qcom-soc.yaml b/Documentation/devicetree/bindings/arm/qcom-soc.yaml
index 27261039d56f..37fdd5a080b7 100644
--- a/Documentation/devicetree/bindings/arm/qcom-soc.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom-soc.yaml
@@ -11,10 +11,10 @@ maintainers:
description: |
Guidelines for new compatibles for SoC blocks/components.
- When adding new compatibles in new bindings, use the format::
+ When adding new compatibles in new bindings, use the format:
qcom,SoC-IP
- For example::
+ For example:
qcom,sdm845-llcc-bwmon
When adding new compatibles to existing bindings, use the format in the
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 50cc18a6ec5e..667607ae2c32 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -1215,7 +1215,7 @@ properties:
items:
items:
- description: |
- MSM chipset ID - an exact match value consisting of two bitfields::
+ MSM chipset ID - an exact match value consisting of two bitfields:
- bits 0-15 - The unique MSM chipset ID
- bits 16-31 - Reserved; should be 0
- description: |
@@ -1241,7 +1241,7 @@ properties:
- items:
- items:
- description: |
- Board ID consisting of three bitfields::
+ Board ID consisting of three bitfields:
- bits 31-24 - Unused
- bits 23-16 - Platform Version Major
- bits 15-8 - Platform Version Minor
diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-soc.yaml b/Documentation/devicetree/bindings/arm/samsung/samsung-soc.yaml
index 653f85997643..ab000befe76d 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-soc.yaml
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-soc.yaml
@@ -11,10 +11,10 @@ maintainers:
description: |
Guidelines for new compatibles for SoC blocks/components.
- When adding new compatibles in new bindings, use the format::
+ When adding new compatibles in new bindings, use the format:
samsung,SoC-IP
- For example::
+ For example:
samsung,exynos5433-cmu-isp
select:
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index dbc0613e427e..395425a70db8 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -73,16 +73,16 @@ properties:
clocks:
description: |
- Several clocks are used, depending on the variant. Typical ones are::
- - bus:: Display AHB clock.
- - byte:: Display byte clock.
- - byte_intf:: Display byte interface clock.
- - core:: Display core clock.
- - core_mss:: Core MultiMedia SubSystem clock.
- - iface:: Display AXI clock.
- - mdp_core:: MDP Core clock.
- - mnoc:: MNOC clock
- - pixel:: Display pixel clock.
+ Several clocks are used, depending on the variant. Typical ones are:
+ - bus: Display AHB clock.
+ - byte: Display byte clock.
+ - byte_intf: Display byte interface clock.
+ - core: Display core clock.
+ - core_mss: Core MultiMedia SubSystem clock.
+ - iface: Display AXI clock.
+ - mdp_core: MDP Core clock.
+ - mnoc: MNOC clock
+ - pixel: Display pixel clock.
minItems: 3
maxItems: 12
diff --git a/Documentation/devicetree/bindings/display/samsung/samsung,fimd.yaml b/Documentation/devicetree/bindings/display/samsung/samsung,fimd.yaml
index ff685031bb2c..729705f419bb 100644
--- a/Documentation/devicetree/bindings/display/samsung/samsung,fimd.yaml
+++ b/Documentation/devicetree/bindings/display/samsung/samsung,fimd.yaml
@@ -41,7 +41,7 @@ properties:
additionalProperties: false
description: |
Timing configuration for lcd i80 interface support.
- The parameters are defined as::
+ The parameters are defined as:
VCLK(internal) __|??????|_____|??????|_____|??????|_____|??????|_____|??
: : : : :
Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
@@ -132,7 +132,7 @@ patternProperties:
"^port@[0-4]+$":
$ref: /schemas/graph.yaml#/properties/port
description: |
- Contains ports with port with index::
+ Contains ports with port with index:
0 - for CAMIF0 input,
1 - for CAMIF1 input,
2 - for CAMIF2 input,
diff --git a/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml b/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml
index a2ddc6803617..07600b49f2f9 100644
--- a/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml
@@ -35,7 +35,7 @@ properties:
gpios:
description: |
- The order of the GPIOs should be the following:: <SDA, SCL>. The GPIO
+ The order of the GPIOs should be the following: <SDA, SCL>. The GPIO
specifier depends on the gpio controller. Required in all cases except
for "samsung,s3c2440-hdmiphy-i2c" whose input/output lines are
permanently wired to the respective client.
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
index ff64225e8281..e002e70580f9 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
@@ -13,7 +13,7 @@ description: |
Bandwidth Monitor measures current throughput on buses between various NoC
fabrics and provides information when it crosses configured thresholds.
- Certain SoCs might have more than one Bandwidth Monitors, for example on SDM845::
+ Certain SoCs might have more than one Bandwidth Monitors, for example on SDM845:
- Measuring the bandwidth between CPUs and Last Level Cache Controller -
called just BWMON,
- Measuring the bandwidth between Last Level Cache Controller and memory
diff --git a/Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml b/Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml
index 5e26e48c7217..0203959c8995 100644
--- a/Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml
+++ b/Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml
@@ -23,7 +23,7 @@ description: |
The each AXI bus has the owned source clock but, has not the only owned power
line. The power line might be shared among one more sub-blocks. So, we can
divide into two type of device as the role of each sub-block. There are two
- type of bus devices as following::
+ type of bus devices as following:
- parent bus device
- passive bus device
@@ -44,8 +44,8 @@ description: |
able to support the bus frequency for all Exynos SoCs.
Detailed correlation between sub-blocks and power line according
- to Exynos SoC::
- - In case of Exynos3250, there are two power line as following::
+ to Exynos SoC:
+ - In case of Exynos3250, there are two power line as following:
VDD_MIF |--- DMC (Dynamic Memory Controller)
VDD_INT |--- LEFTBUS (parent device)
@@ -89,7 +89,7 @@ description: |
|L5 |200000 |200000 |400000 |300000 | ||1000000 |
----------------------------------------------------------
- - In case of Exynos4210, there is one power line as following::
+ - In case of Exynos4210, there is one power line as following:
VDD_INT |--- DMC (parent device, Dynamic Memory Controller)
|--- LEFTBUS
|--- PERIL
@@ -106,7 +106,7 @@ description: |
|--- LCD0
|--- LCD1
- - In case of Exynos4x12, there are two power line as following::
+ - In case of Exynos4x12, there are two power line as following:
VDD_MIF |--- DMC (Dynamic Memory Controller)
VDD_INT |--- LEFTBUS (parent device)
@@ -124,7 +124,7 @@ description: |
|--- LCD0
|--- ISP
- - In case of Exynos5422, there are two power line as following::
+ - In case of Exynos5422, there are two power line as following:
VDD_MIF |--- DREX 0 (parent device, DRAM EXpress controller)
|--- DREX 1
@@ -143,7 +143,7 @@ description: |
|--- FSYS
|--- FSYS2
- - In case of Exynos5433, there is VDD_INT power line as following::
+ - In case of Exynos5433, there is VDD_INT power line as following:
VDD_INT |--- G2D (parent device)
|--- MSCL
|--- GSCL
diff --git a/Documentation/devicetree/bindings/leds/qcom,pm8058-led.yaml b/Documentation/devicetree/bindings/leds/qcom,pm8058-led.yaml
index b409b2a8b5c5..5165bfddcd54 100644
--- a/Documentation/devicetree/bindings/leds/qcom,pm8058-led.yaml
+++ b/Documentation/devicetree/bindings/leds/qcom,pm8058-led.yaml
@@ -10,10 +10,10 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
- The Qualcomm PM8058 contains an LED block for up to six LEDs:: three normal
+ The Qualcomm PM8058 contains an LED block for up to six LEDs: three normal
LEDs, two "flash" LEDs and one "keypad backlight" LED. The names are quoted
because sometimes these LED drivers are used for wildly different things than
- flash or keypad backlight:: their names are more of a suggestion than a
+ flash or keypad backlight: their names are more of a suggestion than a
hard-wired usecase.
Hardware-wise the different LEDs support slightly different output currents.
diff --git a/Documentation/devicetree/bindings/leds/skyworks,aat1290.yaml b/Documentation/devicetree/bindings/leds/skyworks,aat1290.yaml
index a6aaa92dbccd..65576dfdca11 100644
--- a/Documentation/devicetree/bindings/leds/skyworks,aat1290.yaml
+++ b/Documentation/devicetree/bindings/leds/skyworks,aat1290.yaml
@@ -11,7 +11,7 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
- The device is controlled through two pins:: FL_EN and EN_SET. The pins when,
+ The device is controlled through two pins: FL_EN and EN_SET. The pins when,
asserted high, enable flash strobe and movie mode (max 1/2 of flash current)
respectively. In order to add a capability of selecting the strobe signal
source (e.g. CPU or camera sensor) there is an additional switch required,
@@ -39,11 +39,11 @@ properties:
flash-max-microamp:
description: |
Maximum flash LED supply current can be calculated using following
- formula:: I = 1A * 162 kOhm / Rset.
+ formula: I = 1A * 162 kOhm / Rset.
flash-max-timeout-us:
description: |
- Maximum flash timeout can be calculated using following formula::
+ Maximum flash timeout can be calculated using following formula:
T = 8.82 * 10^9 * Ct.
required:
diff --git a/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml b/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml
index 582c6c9cae48..21118e4bae0f 100644
--- a/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml
+++ b/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml
@@ -14,7 +14,7 @@ description: |
hooked up to a pull-up GPIO line and - optionally - the HPD line is hooked up
to another GPIO line.
- Please note:: the maximum voltage for the CEC line is 3.63V, for the HPD and
+ Please note: the maximum voltage for the CEC line is 3.63V, for the HPD and
5V lines it is 5.3V. So you may need some sort of level conversion
circuitry when connecting them to a GPIO line.
diff --git a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml
index 27c4060f2f91..223fcc9f651f 100644
--- a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml
@@ -85,7 +85,7 @@ properties:
description: |
The value of CIU TX and RX clock phase shift value for HS400 mode
operation.
- Valid values for SDR and DDR CIU clock timing::
+ Valid values for SDR and DDR CIU clock timing:
- valid value for tx phase shift and rx phase shift is 0 to 7.
- when CIU clock divider value is set to 3, all possible 8 phase shift
values can be used.
diff --git a/Documentation/devicetree/bindings/mux/mux-consumer.yaml b/Documentation/devicetree/bindings/mux/mux-consumer.yaml
index 9e2d78a78e40..769243a2bf04 100644
--- a/Documentation/devicetree/bindings/mux/mux-consumer.yaml
+++ b/Documentation/devicetree/bindings/mux/mux-consumer.yaml
@@ -13,8 +13,8 @@ description: |
Mux controller consumers should specify a list of mux controllers that they
want to use with a property containing a 'mux-ctrl-list':
- mux-ctrl-list ::= <single-mux-ctrl> [mux-ctrl-list]
- single-mux-ctrl ::= <mux-ctrl-phandle> [mux-ctrl-specifier]
+ mux-ctrl-list := <single-mux-ctrl> [mux-ctrl-list]
+ single-mux-ctrl := <mux-ctrl-phandle> [mux-ctrl-specifier]
mux-ctrl-phandle : phandle to mux controller node
mux-ctrl-specifier : array of #mux-control-cells specifying the
given mux controller (controller specific)
diff --git a/Documentation/devicetree/bindings/phy/samsung,mipi-video-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,mipi-video-phy.yaml
index 16967ef8e9ec..87b6a35b2626 100644
--- a/Documentation/devicetree/bindings/phy/samsung,mipi-video-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,mipi-video-phy.yaml
@@ -13,14 +13,14 @@ maintainers:
description: |
For samsung,s5pv210-mipi-video-phy compatible PHYs the second cell in the
- PHY specifier identifies the PHY and its meaning is as follows::
+ PHY specifier identifies the PHY and its meaning is as follows:
0 - MIPI CSIS 0,
1 - MIPI DSIM 0,
2 - MIPI CSIS 1,
3 - MIPI DSIM 1.
samsung,exynos5420-mipi-video-phy and samsung,exynos5433-mipi-video-phy
- support additional fifth PHY::
+ support additional fifth PHY:
4 - MIPI CSIS 2.
properties:
diff --git a/Documentation/devicetree/bindings/phy/samsung,usb2-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,usb2-phy.yaml
index d9f22a801cbf..7db7605a82e2 100644
--- a/Documentation/devicetree/bindings/phy/samsung,usb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,usb2-phy.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
The first phandle argument in the PHY specifier identifies the PHY, its
meaning is compatible dependent. For the currently supported SoCs (Exynos4210
- and Exynos4212) it is as follows::
+ and Exynos4212) it is as follows:
0 - USB device ("device"),
1 - USB host ("host"),
2 - HSIC0 ("hsic0"),
diff --git a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
index 4562e0468f4f..a1b3d9e6a094 100644
--- a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
For samsung,exynos5250-usbdrd-phy and samsung,exynos5420-usbdrd-phy
compatible PHYs, the second cell in the PHY specifier identifies the
- PHY id, which is interpreted as follows::
+ PHY id, which is interpreted as follows:
0 - UTMI+ type phy,
1 - PIPE3 type phy.
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
index 7b006009ca0e..5e35686eeed3 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
@@ -18,7 +18,7 @@ description: |
All the pin controller nodes should be represented in the aliases node using
the following format 'pinctrl{n}' where n is a unique number for the alias.
- The controller supports three types of interrupts::
+ The controller supports three types of interrupts:
- External GPIO interrupts (see interrupts property in pin controller node);
- External wake-up interrupts - multiplexed (capable of waking up the system
diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml
index 347571e2545a..b67aa170b2c1 100644
--- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml
+++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml
@@ -13,7 +13,7 @@ maintainers:
description: |
The R-Car (RZ/G) System Controller provides power management for the CPU
cores and various coprocessors.
- The power domain IDs for consumers are defined in header files::
+ The power domain IDs for consumers are defined in header files:
include/dt-bindings/power/r8*-sysc.h
properties:
diff --git a/Documentation/devicetree/bindings/power/reset/restart-handler.yaml b/Documentation/devicetree/bindings/power/reset/restart-handler.yaml
index 965a834a3dbe..00c00ec5ec81 100644
--- a/Documentation/devicetree/bindings/power/reset/restart-handler.yaml
+++ b/Documentation/devicetree/bindings/power/reset/restart-handler.yaml
@@ -18,12 +18,12 @@ properties:
priority:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
- A priority ranging from 0 to 255 according to the following guidelines::
- 0:: Restart handler of last resort, with limited restart capabilities.
- 128:: Typical, default restart handler; use if no other restart handler
+ A priority ranging from 0 to 255 according to the following guidelines:
+ 0: Restart handler of last resort, with limited restart capabilities.
+ 128: Typical, default restart handler; use if no other restart handler
is expected to be available, and/or if restart functionality is
sufficient to restart the entire system.
- 255:: Highest priority restart handler, will preempt all other restart handlers.
+ 255: Highest priority restart handler, will preempt all other restart handlers.
minimum: 0
maximum: 255
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
index b704f05ea454..b886495c1396 100644
--- a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
+++ b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
@@ -22,13 +22,13 @@ description: |
Certain regulators support "regulator-initial-mode" and "regulator-mode".
The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h
- and their meaning is::
+ and their meaning is:
1 - Normal regulator voltage output mode.
3 - Low Power which reduces the quiescent current down to only 1uA
The standard "regulator-mode" property can only be used for regulators that
support changing their mode to Low Power Mode during suspend. These
- regulators are:: bucks 2-4 and LDOs 1-35. Also, it only takes effect if the
+ regulators are: bucks 2-4 and LDOs 1-35. Also, it only takes effect if the
regulator has been enabled for the given suspend state using
"regulator-on-in-suspend" and has not been disabled for that state using
"regulator-off-in-suspend".
diff --git a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
index 022c1f197364..b0aa38edf8c2 100644
--- a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
+++ b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
@@ -21,7 +21,7 @@ description: |
conduction mode (FCCM).
The definition of modes is in the datasheet which is available in below link
- and their meaning is::
+ and their meaning is:
0 - Auto mode for power saving, which reducing the switching frequency at light load condition
to maintain high frequency.
1 - FCCM to meet the strict voltage regulation accuracy, which keeping constant switching frequency.
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
index 788ef5c1c446..bc967ead2350 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
@@ -17,7 +17,7 @@ description: |
software perspective it's mostly compatible with the MSM serial UART except
that it supports reading and writing multiple characters at a time.
- Note:: Aliases may be defined to ensure the correct ordering of the UARTs.
+ Note: Aliases may be defined to ensure the correct ordering of the UARTs.
The alias serialN will result in the UART being assigned port N. If any
serialN alias exists, then an alias must exist for each enabled UART. The
serialN aliases should be in a .dts file instead of in a .dtsi file.
diff --git a/Documentation/devicetree/bindings/slimbus/slimbus.yaml b/Documentation/devicetree/bindings/slimbus/slimbus.yaml
index 5a941610ce4e..3910327c8ded 100644
--- a/Documentation/devicetree/bindings/slimbus/slimbus.yaml
+++ b/Documentation/devicetree/bindings/slimbus/slimbus.yaml
@@ -29,7 +29,7 @@ patternProperties:
description: |
Every SLIMbus controller node can contain zero or more child nodes
representing slave devices on the bus. Every SLIMbus slave device is
- uniquely determined by the enumeration address containing 4 fields::
+ uniquely determined by the enumeration address containing 4 fields:
Manufacturer ID, Product code, Device index, and Instance value for the
device.
@@ -48,7 +48,7 @@ patternProperties:
reg:
maxItems: 1
description: |
- Pair of (device index, instande ID), where::
+ Pair of (device index, instande ID), where:
- Device index, which uniquely identifies multiple devices within a
single component.
- Instance ID, can be used for the cases where multiple devices of
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
index bdf482db32aa..b663be3ea5a1 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
@@ -40,7 +40,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/string-array
description: |
Protection domain service name and path for APR service (if supported).
- Possible values are::
+ Possible values are:
"avs/audio", "msm/adsp/audio_pd".
"kernel/elf_loader", "msm/modem/wlan_pd".
"tms/servreg", "msm/adsp/audio_pd".
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
index 26d9bc773ec5..1889139a3f7a 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
@@ -23,7 +23,7 @@ description: |
with a few variations that are captured by the properties here.
A TCS may be triggered from Linux or triggered by the F/W after all the CPUs
- have powered off to facilitate idle power saving. TCS could be classified as::
+ have powered off to facilitate idle power saving. TCS could be classified as:
ACTIVE - Triggered by Linux
SLEEP - Triggered by F/W
WAKE - Triggered by F/W
@@ -76,7 +76,7 @@ properties:
items:
items:
- description: |
- TCS type::
+ TCS type:
- ACTIVE_TCS
- SLEEP_TCS
- WAKE_TCS
@@ -152,7 +152,7 @@ examples:
- |
// For a TCS whose RSC base address is 0x179C0000 and is at a DRV id of
// 2, the register offsets for DRV2 start at 0D00, the register
- // calculations are like this::
+ // calculations are like this:
// DRV0: 0x179C0000
// DRV2: 0x179C0000 + 0x10000 = 0x179D0000
// DRV2: 0x179C0000 + 0x10000 * 2 = 0x179E0000
@@ -182,7 +182,7 @@ examples:
- |
// For a TCS whose RSC base address is 0xAF20000 and is at DRV id of 0, the
// register offsets for DRV0 start at 01C00, the register calculations are
- // like this::
+ // like this:
// DRV0: 0xAF20000
// TCS-OFFSET: 0x1C00
#include <dt-bindings/interrupt-controller/arm-gic.h>
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,wcnss.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,wcnss.yaml
index 4fcae6bedfff..72a7f8cb09ba 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,wcnss.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,wcnss.yaml
@@ -28,7 +28,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description: |
Reference to a node specifying the wcnss "ccu" and "dxe" register blocks.
- The node must be compatible with one of the following::
+ The node must be compatible with one of the following:
- qcom,riva"
- qcom,pronto"
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas-soc.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas-soc.yaml
index 5ddd31f30f26..57c9d3c57021 100644
--- a/Documentation/devicetree/bindings/soc/renesas/renesas-soc.yaml
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas-soc.yaml
@@ -12,10 +12,10 @@ maintainers:
description: |
Guidelines for new compatibles for SoC blocks/components.
- When adding new compatibles in new bindings, use the format::
+ When adding new compatibles in new bindings, use the format:
renesas,SoC-IP
- For example::
+ For example:
renesas,r8a77965-csi2
When adding new compatibles to existing bindings, use the format in the
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
index 47a105a97ecf..bc8c8ba24f9c 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
@@ -45,7 +45,7 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
description: |
- The direction of the dai stream::
+ The direction of the dai stream:
- Q6ASM_DAI_TX_RX (0) for both tx and rx
- Q6ASM_DAI_TX (1) for only tx (Capture/Encode)
- Q6ASM_DAI_RX (2) for only rx (Playback/Decode)
diff --git a/Documentation/devicetree/bindings/thermal/samsung,exynos-thermal.yaml b/Documentation/devicetree/bindings/thermal/samsung,exynos-thermal.yaml
index 29a08b0729ee..3f333db72a71 100644
--- a/Documentation/devicetree/bindings/thermal/samsung,exynos-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/samsung,exynos-thermal.yaml
@@ -40,7 +40,7 @@ properties:
description: |
The Exynos TMU supports generating interrupts when reaching given
temperature thresholds. Number of supported thermal trip points depends
- on the SoC (only first trip points defined in DT will be configured)::
+ on the SoC (only first trip points defined in DT will be configured):
- most of SoC: 4
- samsung,exynos5433-tmu: 8
- samsung,exynos7-tmu: 8
@@ -52,7 +52,7 @@ properties:
- description: |
Shared TMU registers.
- Note:: On Exynos5420, the TRIMINFO register is misplaced for TMU
+ Note: On Exynos5420, the TRIMINFO register is misplaced for TMU
channels 2, 3 and 4 Use "samsung,exynos5420-tmu-ext-triminfo" in
cases, there is a misplaced register, also provide clock to access
that base.
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index a7f58114c02e..90daee616880 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -92,14 +92,14 @@ properties:
clocks:
description: |
- Several clocks are used, depending on the variant. Typical ones are::
- - cfg_noc:: System Config NOC clock.
- - core:: Master/Core clock, has to be >= 125 MHz for SS operation and >=
+ Several clocks are used, depending on the variant. Typical ones are:
+ - cfg_noc: System Config NOC clock.
+ - core: Master/Core clock, has to be >= 125 MHz for SS operation and >=
60MHz for HS operation.
- - iface:: System bus AXI clock.
- - sleep:: Sleep clock, used for wakeup when USB3 core goes into low
+ - iface: System bus AXI clock.
+ - sleep: Sleep clock, used for wakeup when USB3 core goes into low
power mode (U3).
- - mock_utmi:: Mock utmi clock needed for ITP/SOF generation in host
+ - mock_utmi: Mock utmi clock needed for ITP/SOF generation in host
mode. Its frequency should be 19.2MHz.
minItems: 1
maxItems: 9
diff --git a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml
index 8201656b41ed..d99af9f413d0 100644
--- a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml
@@ -87,14 +87,14 @@ properties:
clocks:
description: |
- Several clocks are used, depending on the variant. Typical ones are::
- - cfg_noc:: System Config NOC clock.
- - core:: Master/Core clock, has to be >= 125 MHz for SS operation and >=
+ Several clocks are used, depending on the variant. Typical ones are:
+ - cfg_noc: System Config NOC clock.
+ - core: Master/Core clock, has to be >= 125 MHz for SS operation and >=
60MHz for HS operation.
- - iface:: System bus AXI clock.
- - sleep:: Sleep clock, used for wakeup when USB3 core goes into low
+ - iface: System bus AXI clock.
+ - sleep: Sleep clock, used for wakeup when USB3 core goes into low
power mode (U3).
- - mock_utmi:: Mock utmi clock needed for ITP/SOF generation in host
+ - mock_utmi: Mock utmi clock needed for ITP/SOF generation in host
mode. Its frequency should be 19.2MHz.
minItems: 1
maxItems: 9
--
2.53.0
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: clock: Drop incorrect usage of double '::'
From: Krzysztof Kozlowski @ 2026-06-22 10:16 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Peter Griffin, Alim Akhtar, Michael Turquette,
Stephen Boyd, Brian Masney, Sylwester Nawrocki, Chanwoo Choi,
Sam Protsenko, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Inki Dae, Seung-Woo Kim, Kyungmin Park,
Andi Shyti, Georgi Djakov, Lee Jones, Pavel Machek, Hans Verkuil,
Mauro Carvalho Chehab, Ulf Hansson, Peter Rosin, Vinod Koul,
Neil Armstrong, Linus Walleij, Geert Uytterhoeven, Magnus Damm,
Sebastian Reichel, Javier Martinez Canillas, Liam Girdwood,
Mark Brown, Greg Kroah-Hartman, Jiri Slaby, Srinivas Kandagatla,
Bartlomiej Zolnierkiewicz, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Jonathan Marek, Taniya Das, Robert Marko,
Christian Marangi, Stephan Gerhold, Adam Skladowski,
Sireesh Kodali, Barnabas Czeman, Imran Shaik,
Sricharan Ramabadhran, Anusha Rao, Luo Jie, Tomasz Figa,
Chanho Park, Sunyeal Hong, Shin Son, Krishna Manikandan,
Jacek Anaszewski, Jaehoon Chung, Marek Szyprowski, Alina Yu,
Andy Gross, Niklas Söderlund, Wesley Cheng, linux-arm-msm,
devicetree, linux-kernel, linux-arm-kernel, linux-samsung-soc,
linux-clk, dri-devel, freedreno, linux-i2c, linux-pm, linux-leds,
linux-media, linux-mmc, linux-phy, linux-gpio, linux-renesas-soc,
linux-serial, linux-sound, linux-usb
Cc: Krzysztof Kozlowski
There is no use of double colon '::' in YAML. OTOH, the literal style
block, e.g. using '|' treats all characters as content [1] therefore
single use of ':' in descriptions is perfectly fine, whenever '|' is
used.
Cleanup existing code, so the confusing style won't be re-used in new
contributions.
Link: https://yaml.org/spec/1.2.2/#literal-style [1]
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
I split the patches to avoid bounces from mailing list due to email size.
This can go via clock tree (no dependencies)... or both could go via
Rob's tree.
---
.../devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-apq8064.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-apq8084.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-ipq6018.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-ipq8064.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-mdm9607.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-mdm9615.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-msm8660.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-msm8909.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-msm8916.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-msm8953.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-msm8974.yaml | 2 +-
.../devicetree/bindings/clock/qcom,gcc-sdm660.yaml | 2 +-
Documentation/devicetree/bindings/clock/qcom,gpucc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,ipq5018-gcc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,ipq9574-gcc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,qca8k-nsscc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml | 2 +-
Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml | 2 +-
.../devicetree/bindings/clock/qcom,sm8350-videocc.yaml | 2 +-
Documentation/devicetree/bindings/clock/qcom,videocc.yaml | 2 +-
.../devicetree/bindings/clock/samsung,exynos5260-clock.yaml | 6 +++---
.../devicetree/bindings/clock/samsung,exynos5410-clock.yaml | 2 +-
.../devicetree/bindings/clock/samsung,exynos5433-clock.yaml | 2 +-
.../devicetree/bindings/clock/samsung,exynos7-clock.yaml | 2 +-
.../devicetree/bindings/clock/samsung,exynos850-clock.yaml | 2 +-
.../bindings/clock/samsung,exynosautov9-clock.yaml | 2 +-
.../bindings/clock/samsung,exynosautov920-clock.yaml | 2 +-
.../devicetree/bindings/clock/samsung,s5pv210-clock.yaml | 2 +-
32 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
index 53a5ab319159..6863db9bd092 100644
--- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm display clock control module provides the clocks, resets and power
domains on SM8150/SM8250/SM8350.
- See also::
+ See also:
include/dt-bindings/clock/qcom,dispcc-sm8150.h
include/dt-bindings/clock/qcom,dispcc-sm8250.h
include/dt-bindings/clock/qcom,dispcc-sm8350.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
index 27df7e3e5bf3..68532244901e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on APQ8064.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8960.h
include/dt-bindings/reset/qcom,gcc-msm8960.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
index 0a0a26d9beab..1c022e75fd71 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on APQ8084.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-apq8084.h
include/dt-bindings/reset/qcom,gcc-apq8084.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq6018.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq6018.yaml
index 4d2614d4f368..c7fb84438db7 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq6018.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq6018.yaml
@@ -15,7 +15,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on IPQ6018.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-ipq6018.h
include/dt-bindings/reset/qcom,gcc-ipq6018.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
index a71557395c01..b4d3175780bc 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on IPQ8064.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
include/dt-bindings/reset/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9607.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9607.yaml
index d7da30b0e7ee..0a7be7583bdd 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9607.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9607.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-mdm9607.h
allOf:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9615.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9615.yaml
index 418dea31eb62..0656d5ee448d 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9615.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-mdm9615.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-mdm9615.h
allOf:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
index e03b6d0acdb6..70c9da1f35c2 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks and resets on
MSM8660
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8660.h
include/dt-bindings/reset/qcom,gcc-msm8660.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
index ce1f5a60bd8c..2edb6c251d99 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on MSM8909, MSM8917 or QM215.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8909.h
include/dt-bindings/clock/qcom,gcc-msm8917.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
index 258b6b93deca..af4b639ea8c3 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on MSM8916 or MSM8939.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8916.h
include/dt-bindings/clock/qcom,gcc-msm8939.h
include/dt-bindings/reset/qcom,gcc-msm8916.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml
index ced3118c8580..fc0360554f68 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml
@@ -15,7 +15,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on MSM8937, MSM8940, MSM8953 or SDM439.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8917.h
include/dt-bindings/clock/qcom,gcc-msm8953.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml
index 929fafc84c19..378dfe7854ac 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml
@@ -15,7 +15,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on MSM8974 (all variants) and MSM8226.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
include/dt-bindings/reset/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml
index 724ce0491118..72aaf699cf70 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on SDM630, SDM636 and SDM660
- See also::
+ See also:
include/dt-bindings/clock/qcom,gcc-sdm660.h (qcom,gcc-sdm630 and qcom,gcc-sdm660)
$ref: qcom,gcc.yaml#
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
index 4cdff6161bf0..3ac4419009a9 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm graphics clock control module provides the clocks, resets and power
domains on Qualcomm SoCs.
- See also::
+ See also:
include/dt-bindings/clock/qcom,gpucc-sdm845.h
include/dt-bindings/clock/qcom,gpucc-sa8775p.h
include/dt-bindings/clock/qcom,gpucc-sc7180.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq5018-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq5018-gcc.yaml
index 489d0fc5607c..9925b931ecad 100644
--- a/Documentation/devicetree/bindings/clock/qcom,ipq5018-gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq5018-gcc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on IPQ5018
- See also::
+ See also:
include/dt-bindings/clock/qcom,ipq5018-gcc.h
include/dt-bindings/reset/qcom,ipq5018-gcc.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
index 27ae9938febc..5b128fa841aa 100644
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on IPQ9574
- See also::
+ See also:
include/dt-bindings/clock/qcom,ipq9574-gcc.h
include/dt-bindings/reset/qcom,ipq9574-gcc.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,qca8k-nsscc.yaml b/Documentation/devicetree/bindings/clock/qcom,qca8k-nsscc.yaml
index 61473385da2d..3da10c364a85 100644
--- a/Documentation/devicetree/bindings/clock/qcom,qca8k-nsscc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,qca8k-nsscc.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm NSS clock control module provides the clocks and resets
on QCA8386(switch mode)/QCA8084(PHY mode)
- See also::
+ See also:
include/dt-bindings/clock/qcom,qca8k-nsscc.h
include/dt-bindings/reset/qcom,qca8k-nsscc.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml
index 734880805c1b..bedbdabef672 100644
--- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm graphics clock control module provides the clocks, resets and power
domains on Qualcomm SoCs.
- See also::
+ See also:
include/dt-bindings/clock/qcom,qcm2290-gpucc.h
properties:
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml
index ab97d4b7dba8..b6c835bfd0d9 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml
@@ -12,7 +12,7 @@ maintainers:
description: |
The clock enumerators are defined in <dt-bindings/clock/qcom,rpmcc.h> and
- come in pairs:: FOO_CLK followed by FOO_A_CLK. The latter clock is
+ come in pairs: FOO_CLK followed by FOO_A_CLK. The latter clock is
an "active" clock, which means that the consumer only care that the clock is
available when the apps CPU subsystem is active, i.e. not suspended or in
deep idle. If it is important that the clock keeps running during system
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
index 99ab9106009f..fd06ac9bceb9 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm LPASS core and audio clock control module provides the clocks and
power domains on SC7280.
- See also::
+ See also:
include/dt-bindings/clock/qcom,lpasscorecc-sc7280.h
include/dt-bindings/clock/qcom,lpassaudiocc-sc7280.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml
index 273d66e245c5..f235b4e24cc7 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm LPASS core and audio clock control module provides the clocks,
and reset on SC8280XP.
- See also::
+ See also:
include/dt-bindings/clock/qcom,lpasscc-sc8280xp.h
properties:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml
index 8cbab3fbb660..d7e1938b5e1b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-lpasscc.yaml
@@ -14,7 +14,7 @@ description: |
Qualcomm LPASS core and audio clock controllers provide audio-related resets
on SM6115 and its derivatives.
- See also::
+ See also:
include/dt-bindings/clock/qcom,sm6115-lpasscc.h
properties:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml
index 5c2ecec0624e..a986ab4ce7c7 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm video clock control module provides the clocks, resets and power
domains on Qualcomm SoCs.
- See also::
+ See also:
include/dt-bindings/clock/qcom,videocc-sm8350.h
include/dt-bindings/reset/qcom,videocc-sm8350.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
index f4ff9acef9d5..124d259fc85e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
@@ -13,7 +13,7 @@ description: |
Qualcomm video clock control module provides the clocks, resets and power
domains on Qualcomm SoCs.
- See also::
+ See also:
include/dt-bindings/clock/qcom,sm6350-videocc.h
include/dt-bindings/clock/qcom,videocc-sc7180.h
include/dt-bindings/clock/qcom,videocc-sc7280.h
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos5260-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos5260-clock.yaml
index b05f83533e3d..56ab972c3da5 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynos5260-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos5260-clock.yaml
@@ -14,17 +14,17 @@ maintainers:
description: |
Expected external clocks, defined in DTS as fixed-rate clocks with a matching
- name::
+ name:
- "fin_pll" - PLL input clock from XXTI
- "xrtcxti" - input clock from XRTCXTI
- "ioclk_pcm_extclk" - pcm external operation clock
- "ioclk_spdif_extclk" - spdif external operation clock
- "ioclk_i2s_cdclk" - i2s0 codec clock
- Phy clocks::
+ Phy clocks:
There are several clocks which are generated by specific PHYs. These clocks
are fed into the clock controller and then routed to the hardware blocks.
- These clocks are defined as fixed clocks in the driver with following names::
+ These clocks are defined as fixed clocks in the driver with following names:
- "phyclk_dptx_phy_ch3_txd_clk" - dp phy clock for channel 3
- "phyclk_dptx_phy_ch2_txd_clk" - dp phy clock for channel 2
- "phyclk_dptx_phy_ch1_txd_clk" - dp phy clock for channel 1
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos5410-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos5410-clock.yaml
index b737c9d35a1c..1d907dd8fbf1 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynos5410-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos5410-clock.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
Expected external clocks, defined in DTS as fixed-rate clocks with a matching
- name::
+ name:
- "fin_pll" - PLL input clock from XXTI
All available clocks are defined as preprocessor macros in
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos5433-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos5433-clock.yaml
index 3f9326e09f79..8a289f1e2ace 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynos5433-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos5433-clock.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
Expected external clocks, defined in DTS as fixed-rate clocks with a matching
- name::
+ name:
- "oscclk" - PLL input clock from XXTI
All available clocks are defined as preprocessor macros in
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos7-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos7-clock.yaml
index c137c6744ef9..a51cd4fafb41 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynos7-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos7-clock.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
Expected external clocks, defined in DTS as fixed-rate clocks with a matching
- name::
+ name:
- "fin_pll" - PLL input clock from XXTI
All available clocks are defined as preprocessor macros in
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
index cdc5ded59fe5..68c2fd318765 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
@@ -17,7 +17,7 @@ description: |
Exynos850 clock controller is comprised of several CMU units, generating
clocks for different domains. Those CMU units are modeled as separate device
tree nodes, and might depend on each other. Root clocks in that clock tree are
- two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
+ two external clocks: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
clocks must be defined as fixed-rate clocks in dts.
CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynosautov9-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynosautov9-clock.yaml
index 32f39e543b36..e9d17d48b4f3 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynosautov9-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynosautov9-clock.yaml
@@ -17,7 +17,7 @@ description: |
Exynos Auto v9 clock controller is comprised of several CMU units, generating
clocks for different domains. Those CMU units are modeled as separate device
tree nodes, and might depend on each other. Root clocks in that clock tree are
- two external clocks:: OSCCLK/XTCXO (26 MHz) and RTCCLK/XrtcXTI (32768 Hz).
+ two external clocks: OSCCLK/XTCXO (26 MHz) and RTCCLK/XrtcXTI (32768 Hz).
The external OSCCLK must be defined as fixed-rate clock in dts.
CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml
index 6b1fc61a2ff9..475db824d4d3 100644
--- a/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,exynosautov920-clock.yaml
@@ -17,7 +17,7 @@ description: |
ExynosAuto v920 clock controller is comprised of several CMU units, generating
clocks for different domains. Those CMU units are modeled as separate device
tree nodes, and might depend on each other. Root clocks in that clock tree are
- two external clocks:: OSCCLK/XTCXO (38.4 MHz) and RTCCLK/XrtcXTI (32768 Hz).
+ two external clocks: OSCCLK/XTCXO (38.4 MHz) and RTCCLK/XrtcXTI (32768 Hz).
The external OSCCLK must be defined as fixed-rate clock in dts.
CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
diff --git a/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.yaml
index 67a33665cf00..b1617d96d3fb 100644
--- a/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.yaml
@@ -14,7 +14,7 @@ maintainers:
description: |
Expected external clocks, defined in DTS as fixed-rate clocks with a matching
- name::
+ name:
- "xxti" - external crystal oscillator connected to XXTI and XXTO pins of
the SoC,
- "xusbxti" - external crystal oscillator connected to XUSBXTI and XUSBXTO
--
2.53.0
^ permalink raw reply related
* [PATCH v3 2/2] selftests: tty: add base regression test for n_gsm line discipline
From: Weiming Shi @ 2026-06-20 16:56 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi
In-Reply-To: <20260620165616.354233-2-bestswngs@gmail.com>
n_gsm has no selftest coverage. Add a base functional regression test
that drives the line discipline over a local pty pair, so no real serial
hardware or modem is required, and exercises the GSM 07.10 / 3GPP TS 27.010
basic-option mux from userspace.
The test attaches N_GSM to the pty master, then:
- basic: brings up the mux (SETCONF, initiator side), drives the
DLCI 0 control channel SABM/UA handshake and tears it down.
- getconf: round-trips GSMIOC_GETCONF/GSMIOC_SETCONF and checks the
configuration is preserved.
- data_dlci: opens a data DLCI (DLCI 1) via the SABM/UA exchange and
verifies the responder side answers, covering the control
-> data DLCI path.
Frames are encoded by hand against 3GPP TS 27.010 (address EA/C-R/DLCI
bits, SABM/UA/UIH control fields, the reversed CRC-8 FCS) with the clause
numbers referenced in the comments, so the test doubles as a small,
readable description of the on-wire format.
It is a functional/regression test, not a race reproducer: it gives the
subsystem a green baseline to catch behavioural regressions, including in
the gsm_queue() control-frame dispatch path.
Wire it into the tty selftest Makefile, add CONFIG_N_GSM=y to the config
fragment, and ignore the built binary. The test SKIPs cleanly when N_GSM
is not built, /dev/ptmx is missing, or it lacks the capability to attach
the ldisc.
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
---
tools/testing/selftests/tty/.gitignore | 1 +
tools/testing/selftests/tty/Makefile | 2 +-
tools/testing/selftests/tty/config | 1 +
tools/testing/selftests/tty/tty_n_gsm_test.c | 344 +++++++++++++++++++
4 files changed, 347 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/tty/tty_n_gsm_test.c
diff --git a/tools/testing/selftests/tty/.gitignore b/tools/testing/selftests/tty/.gitignore
index 2453685d2..e3fcee15e 100644
--- a/tools/testing/selftests/tty/.gitignore
+++ b/tools/testing/selftests/tty/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
tty_tiocsti_test
tty_tstamp_update
+tty_n_gsm_test
diff --git a/tools/testing/selftests/tty/Makefile b/tools/testing/selftests/tty/Makefile
index 7f6fbe5a0..ae546d0d4 100644
--- a/tools/testing/selftests/tty/Makefile
+++ b/tools/testing/selftests/tty/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS = -O2 -Wall
-TEST_GEN_PROGS := tty_tstamp_update tty_tiocsti_test
+TEST_GEN_PROGS := tty_tstamp_update tty_tiocsti_test tty_n_gsm_test
LDLIBS += -lcap
include ../lib.mk
diff --git a/tools/testing/selftests/tty/config b/tools/testing/selftests/tty/config
index c6373aba6..66a5ffc9e 100644
--- a/tools/testing/selftests/tty/config
+++ b/tools/testing/selftests/tty/config
@@ -1 +1,2 @@
CONFIG_LEGACY_TIOCSTI=y
+CONFIG_N_GSM=y
diff --git a/tools/testing/selftests/tty/tty_n_gsm_test.c b/tools/testing/selftests/tty/tty_n_gsm_test.c
new file mode 100644
index 000000000..064231512
--- /dev/null
+++ b/tools/testing/selftests/tty/tty_n_gsm_test.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * n_gsm line discipline test
+ *
+ * Exercise the n_gsm (GSM 07.10 mux) control paths over a pty, so the driver
+ * can be regression-tested without the real modem hardware. The test attaches
+ * the ldisc, configures the mux, opens DLCI 0, drives a control frame through
+ * the receive path (reaching gsm_control_reply()) and reconfigures, which
+ * tears the mux down and frees the DLCI. It is a functional coverage test of
+ * the receive and teardown paths, not a reproducer for any specific race.
+ *
+ * The frame encoding follows 3GPP TS 07.10 (a.k.a. 27.010), basic option.
+ *
+ * Requires CONFIG_N_GSM and CAP_NET_ADMIN to attach the ldisc.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <time.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <linux/tty.h>
+#include <linux/gsmmux.h>
+
+#include "../kselftest_harness.h"
+
+#ifndef N_GSM0710
+#define N_GSM0710 21
+#endif
+
+/*
+ * GSM 07.10 basic option framing. Field encodings below are from
+ * 3GPP TS 07.10 (a.k.a. 27.010): the basic-option flag (section 5.2.6.1),
+ * the address field with EA/C-R/DLCI bits (5.2.1.2, command vs response
+ * C/R from table 1), the control field codings (5.2.1.3, table 2), the
+ * length field (5.2.1.5), and the control-channel message types (5.4.6.3).
+ */
+#define GSM0_SOF 0xf9 /* basic-option flag, 1001 1111 */
+#define ADDR_DLCI0 0x03 /* EA=1, C/R=1, DLCI=0 (command) */
+#define ADDR_DLCI0_RSP 0x01 /* EA=1, C/R=0, DLCI=0 (response) */
+#define ADDR_DLCI1 0x07 /* EA=1, C/R=1, DLCI=1 (command) */
+#define GSM_PF 0x10 /* poll/final bit */
+#define CTRL_SABM (0x2f | GSM_PF) /* SABM command */
+#define CTRL_UA (0x63 | GSM_PF) /* UA, the SABM acknowledgment */
+#define CTRL_UIH 0xef /* UIH command/response */
+#define INIT_FCS 0xff
+#define CMD_TEST_EA 0x23 /* (CMD_TEST << 1) | EA, type 5.4.6.3.4 */
+
+#define MAX_FRAME 64
+
+/* Reversed CRC-8 table (poly 0x07), from 3GPP TS 07.10 annex B.3.5. */
+static const unsigned char gsm_fcs8[256] = {
+0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf,
+};
+
+static unsigned char fcs_header(const unsigned char *p, int n)
+{
+ unsigned char fcs = INIT_FCS;
+ int i;
+
+ for (i = 0; i < n; i++)
+ fcs = gsm_fcs8[fcs ^ p[i]];
+ return 0xff - fcs;
+}
+
+/*
+ * Build a GSM0 frame: SOF addr ctrl len [data] FCS SOF.
+ * Returns the frame length, or -1 if it would not fit in MAX_FRAME.
+ */
+static int build_frame(unsigned char *out, unsigned char addr,
+ unsigned char ctrl, const unsigned char *data, int dlen)
+{
+ unsigned char hdr[3] = { addr, ctrl, (unsigned char)((dlen << 1) | 1) };
+ int i = 0, j;
+
+ if (dlen < 0 || dlen + 6 > MAX_FRAME)
+ return -1;
+
+ out[i++] = GSM0_SOF;
+ out[i++] = addr;
+ out[i++] = ctrl;
+ out[i++] = (unsigned char)((dlen << 1) | 1);
+ for (j = 0; j < dlen; j++)
+ out[i++] = data[j];
+ out[i++] = fcs_header(hdr, 3);
+ out[i++] = GSM0_SOF;
+ return i;
+}
+
+static int gsm_setconf(int fd, int mtu)
+{
+ struct gsm_config c;
+
+ memset(&c, 0, sizeof(c));
+ c.adaption = 1;
+ c.encapsulation = 0; /* basic option framing */
+ c.initiator = 0; /* responder: the peer (master side) drives DLCI 0 */
+ c.mru = 64;
+ c.mtu = mtu;
+ c.i = 1; /* UIH frames */
+ c.k = 2; /* window size */
+ /* Short timers and a single retry so open/close handshakes and the
+ * teardown complete quickly within the test.
+ */
+ c.t1 = 1;
+ c.t2 = 1;
+ c.n2 = 1;
+ return ioctl(fd, GSMIOC_SETCONF, &c);
+}
+
+/*
+ * Open a pty pair with a raw master and the n_gsm ldisc on the slave.
+ * Returns 0 and fills *mfd (master) / *sfd (slave/ldisc) on success, or
+ * -errno otherwise.
+ */
+static int gsm_open(int *mfd, int *sfd)
+{
+ int ldisc = N_GSM0710;
+ char sname[128];
+ struct termios tio;
+ int m, s, e;
+
+ m = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+ if (m < 0)
+ return -errno;
+ if (grantpt(m) || unlockpt(m) || ptsname_r(m, sname, sizeof(sname))) {
+ e = errno;
+ close(m);
+ return -e;
+ }
+ s = open(sname, O_RDWR | O_NOCTTY);
+ if (s < 0) {
+ e = errno;
+ close(m);
+ return -e;
+ }
+ if (tcgetattr(m, &tio) == 0) {
+ cfmakeraw(&tio);
+ tcsetattr(m, TCSANOW, &tio);
+ }
+ if (ioctl(s, TIOCSETD, &ldisc) < 0) {
+ e = errno;
+ close(s);
+ close(m);
+ return -e;
+ }
+ *mfd = m;
+ *sfd = s;
+ return 0;
+}
+
+static long now_ms(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+/*
+ * Wait until the mux sends a frame on DLCI 0 with the given address and
+ * control field, e.g. the UA that acknowledges SABM (addr 0x03), or the
+ * CMD_TEST reply (response addr 0x01). Returns 1 if a matching frame header
+ * (SOF, addr, ctrl) is seen, 0 on timeout. Matching the SOF + address +
+ * control sequence (rather than a lone control byte) avoids false hits on
+ * FCS or payload bytes that happen to equal the control value.
+ */
+static int wait_for_frame(int mfd, unsigned char addr, unsigned char ctrl,
+ int timeout_ms)
+{
+ struct pollfd pfd = { .fd = mfd, .events = POLLIN };
+ long deadline = now_ms() + timeout_ms;
+ unsigned char buf[256];
+ int left;
+
+ while ((left = deadline - now_ms()) > 0) {
+ int ret, n, i;
+
+ ret = poll(&pfd, 1, left);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ return 0;
+ }
+ if (ret == 0 || !(pfd.revents & POLLIN))
+ continue;
+
+ n = read(mfd, buf, sizeof(buf));
+ if (n <= 0)
+ continue;
+ for (i = 0; i + 2 < n; i++) {
+ if (buf[i] == GSM0_SOF && buf[i + 1] == addr &&
+ buf[i + 2] == ctrl)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+FIXTURE(n_gsm)
+{
+ int mfd; /* pty master */
+ int sfd; /* pty slave, carrying the n_gsm ldisc */
+};
+
+FIXTURE_SETUP(n_gsm)
+{
+ int ret;
+
+ /* So FIXTURE_TEARDOWN does not close fd 0 if setup bails early. */
+ self->mfd = -1;
+ self->sfd = -1;
+
+ ret = gsm_open(&self->mfd, &self->sfd);
+
+ if (ret == -EPERM || ret == -EACCES)
+ SKIP(return, "need CAP_NET_ADMIN to attach n_gsm ldisc");
+ if (ret == -EINVAL || ret == -ENODEV)
+ SKIP(return, "CONFIG_N_GSM not enabled");
+ if (ret == -ENOENT)
+ SKIP(return, "no pty support (/dev/ptmx missing)");
+ ASSERT_EQ(ret, 0)
+ TH_LOG("gsm_open failed: %d", ret);
+}
+
+FIXTURE_TEARDOWN(n_gsm)
+{
+ if (self->sfd >= 0)
+ close(self->sfd);
+ if (self->mfd >= 0)
+ close(self->mfd);
+}
+
+/*
+ * Configure the mux, open DLCI 0 and push a control frame through the receive
+ * path, then reconfigure to tear the mux down. This needs no hardware and
+ * verifies the n_gsm receive/teardown paths are reachable and do not crash.
+ */
+TEST_F(n_gsm, basic)
+{
+ unsigned char sabm[MAX_FRAME], cmd_test[MAX_FRAME];
+ /*
+ * CMD_TEST control command: cmd byte = (CMD_TEST << 1) | EA, then a
+ * length-EA byte (0x01) meaning zero bytes of test data.
+ */
+ unsigned char payload[2] = { CMD_TEST_EA, 0x01 };
+ int slen, tlen;
+
+ /* Activate the mux; this allocates DLCI 0. */
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ slen = build_frame(sabm, ADDR_DLCI0, CTRL_SABM, NULL, 0);
+ tlen = build_frame(cmd_test, ADDR_DLCI0, CTRL_UIH, payload, sizeof(payload));
+ ASSERT_GT(slen, 0);
+ ASSERT_GT(tlen, 0);
+
+ /* Open DLCI 0 and wait for the UA reply confirming it reached OPEN. */
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ ASSERT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 0 did not open (no UA reply)");
+
+ /*
+ * Drive a CMD_TEST control frame; the receive path reaches
+ * gsm_control_reply(), which sends a CMD_TEST reply back on the
+ * response address. Wait for that reply so we know the frame was
+ * processed, rather than sleeping.
+ */
+ ASSERT_EQ(write(self->mfd, cmd_test, tlen), tlen);
+ EXPECT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0_RSP, CTRL_UIH, 1000), 1)
+ TH_LOG("no CMD_TEST reply seen");
+
+ /* Reconfigure: tears the mux down and frees DLCI 0. */
+ EXPECT_EQ(gsm_setconf(self->sfd, 127), 0);
+}
+
+/*
+ * Configure the mux and read the configuration back with GSMIOC_GETCONF,
+ * checking the value round-trips.
+ */
+TEST_F(n_gsm, getconf)
+{
+ struct gsm_config c;
+
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ memset(&c, 0, sizeof(c));
+ ASSERT_EQ(ioctl(self->sfd, GSMIOC_GETCONF, &c), 0)
+ TH_LOG("GSMIOC_GETCONF failed: %m");
+ EXPECT_EQ(c.mtu, 64u);
+}
+
+/*
+ * Open DLCI 0, then open a data channel (DLCI 1) with SABM and check the mux
+ * acknowledges it with a UA. This exercises gsm_dlci_alloc() and the data DLCI
+ * open path, not just the control channel.
+ */
+TEST_F(n_gsm, data_dlci)
+{
+ unsigned char sabm[MAX_FRAME];
+ int slen;
+
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ slen = build_frame(sabm, ADDR_DLCI0, CTRL_SABM, NULL, 0);
+ ASSERT_GT(slen, 0);
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ ASSERT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 0 did not open");
+
+ /* Open DLCI 1 (a data channel) and wait for its UA. */
+ slen = build_frame(sabm, ADDR_DLCI1, CTRL_SABM, NULL, 0);
+ ASSERT_GT(slen, 0);
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ EXPECT_EQ(wait_for_frame(self->mfd, ADDR_DLCI1, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 1 did not open (no UA reply)");
+
+ /* Tear the mux down. */
+ EXPECT_EQ(gsm_setconf(self->sfd, 127), 0);
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/2] tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
From: Weiming Shi @ 2026-06-20 16:56 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi, stable
In-Reply-To: <20260620165616.354233-2-bestswngs@gmail.com>
The receive worker (flush_to_ldisc -> gsmld_receive_buf -> gsm0_receive/
gsm1_receive -> gsm_queue) reads gsm->dlci[address] and dispatches the
frame via dlci->data() without holding gsm->mutex. The control handlers
reached through dlci->data() then re-read gsm->dlci[]: gsm_control_reply()
re-reads gsm->dlci[0], while gsm_control_modem() (MSC), gsm_control_rls()
(RLS) and gsm_control_negotiation() (PN) re-read gsm->dlci[addr] for the
DLCI named in the command - a different channel from the one the frame
was addressed to.
Concurrently GSMIOC_SETCONF -> gsm_config() -> gsm_cleanup_mux() takes
gsm->mutex and releases every DLCI via gsm_dlci_release() -> dlci_put().
When the last reference is dropped the destructor gsm_dlci_free() clears
gsm->dlci[addr] and frees the object. If the worker dereferences one of
those DLCIs while it is being freed, it touches freed memory.
A peer that drives DLCI 0 control frames (e.g. CMD_TEST) while the mux
owner reconfigures the line discipline with GSMIOC_SETCONF can therefore
trigger a use-after-free:
BUG: KASAN: slab-use-after-free in gsm_control_reply.isra.0
Read of size 8 at addr ffff888029ae9000 by task kworker/u16:2/46
Workqueue: events_unbound flush_to_ldisc
Call Trace:
gsm_control_reply.isra.0 (drivers/tty/n_gsm.c:1494)
gsm_dlci_command (drivers/tty/n_gsm.c:2477)
gsmld_receive_buf (drivers/tty/n_gsm.c:3616)
tty_ldisc_receive_buf (drivers/tty/tty_buffer.c:398)
tty_port_default_receive_buf (drivers/tty/tty_port.c:37)
flush_to_ldisc (drivers/tty/tty_buffer.c:502)
process_one_work
worker_thread
kthread
Freed by task 5110:
kfree
gsm_cleanup_mux (drivers/tty/n_gsm.c:3161)
gsmld_ioctl (drivers/tty/n_gsm.c:3415)
tty_ioctl
Pin each DLCI across the dereference with its existing tty_port reference.
gsm_dlci_open_get() looks gsm->dlci[addr] up under gsm->mutex and, if
present, takes a dlci_get() reference before dropping the mutex; the
caller releases it with gsm_dlci_unget() once it is done. While the
reference is held the kref cannot reach zero, so gsm_dlci_free() cannot
run and the object stays live. gsm_queue() pins the addressed DLCI for
the UI/UIH dispatch, and gsm_control_modem(), gsm_control_rls() and
gsm_control_negotiation() each pin the DLCI they operate on; the addr
range check stays at the call site so a malformed frame cannot index
gsm->dlci[] out of bounds.
The reference is taken only under the mutex, around the lookup; the mutex
is released before dlci->data() and before the data-path work
(gsm_process_modem(), tty_flip_buffer_push(), gsm_data_queue(), ...), so
the receive/transmit path is not serialised by gsm->mutex and its timing
is unaffected.
Attaching the n_gsm line discipline requires CAP_NET_ADMIN (gsmld_open()
uses capable(), not ns_capable()), so this is a local denial of service
for a privileged mux owner whose control channel is driven by an
untrusted peer on the serial link while it reconfigures; harden the
receive path regardless.
Fixes: 6ab8fba7fcb0 ("tty: n_gsm: Added refcount usage to gsm_mux and gsm_dlci structs")
Cc: stable@vger.kernel.org
Reported-by: Xiang Mei <xmei5@asu.edu>
Link: https://lore.kernel.org/all/DJ7OKN8EMAK8.22CE0B8NZXD73@gmail.com/
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
drivers/tty/n_gsm.c | 73 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 67 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c13e050de..771b49000 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -453,6 +453,8 @@ static const u8 gsm_fcs8[256] = {
#define GOOD_FCS 0xCF
static void gsm_dlci_close(struct gsm_dlci *dlci);
+static struct gsm_dlci *gsm_dlci_open_get(struct gsm_mux *gsm, unsigned int addr);
+static void gsm_dlci_unget(struct gsm_dlci *dlci);
static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len);
static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk);
static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
@@ -1695,9 +1697,8 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
addr >>= 1;
/* Closed port, or invalid ? */
- if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
+ if (addr == 0 || addr >= NUM_DLCI)
return;
- dlci = gsm->dlci[addr];
/* Must be at least one byte following the EA */
if ((cl - len) < 1)
@@ -1711,12 +1712,18 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
if (len < 1)
return;
+ /* Hold the DLCI until we are done; see gsm_dlci_open_get(). */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL)
+ return;
+
tty = tty_port_tty_get(&dlci->port);
gsm_process_modem(tty, dlci, modem, cl);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
+ gsm_dlci_unget(dlci);
gsm_control_reply(gsm, CMD_MSC, data, clen);
}
@@ -1746,15 +1753,22 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
/* Invalid DLCI? */
params = (struct gsm_dlci_param_bits *)data;
addr = FIELD_GET(PN_D_FIELD_DLCI, params->d_bits);
- if (addr == 0 || addr >= NUM_DLCI || !gsm->dlci[addr]) {
+ if (addr == 0 || addr >= NUM_DLCI) {
+ gsm->open_error++;
+ return;
+ }
+
+ /* Hold the DLCI until we are done; see gsm_dlci_open_get(). */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL) {
gsm->open_error++;
return;
}
- dlci = gsm->dlci[addr];
/* Too late for parameter negotiation? */
if ((!cr && dlci->state == DLCI_OPENING) || dlci->state == DLCI_OPEN) {
gsm->open_error++;
+ gsm_dlci_unget(dlci);
return;
}
@@ -1765,6 +1779,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
pr_info("%s PN failed\n", __func__);
gsm->open_error++;
gsm_dlci_close(dlci);
+ gsm_dlci_unget(dlci);
return;
}
@@ -1785,6 +1800,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
pr_info("%s PN in invalid state\n", __func__);
gsm->open_error++;
}
+ gsm_dlci_unget(dlci);
}
/**
@@ -1800,6 +1816,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
{
+ struct gsm_dlci *dlci;
struct tty_port *port;
unsigned int addr = 0;
u8 bits;
@@ -1817,14 +1834,18 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
return;
addr >>= 1;
/* Closed port, or invalid ? */
- if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
+ if (addr == 0 || addr >= NUM_DLCI)
return;
/* No error ? */
bits = *dp;
if ((bits & 1) == 0)
return;
- port = &gsm->dlci[addr]->port;
+ /* Hold the DLCI until we are done; see gsm_dlci_open_get(). */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL)
+ return;
+ port = &dlci->port;
if (bits & 2)
tty_insert_flip_char(port, 0, TTY_OVERRUN);
@@ -1835,6 +1856,7 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
tty_flip_buffer_push(port);
+ gsm_dlci_unget(dlci);
gsm_control_reply(gsm, CMD_RLS, data, clen);
}
@@ -2711,6 +2733,35 @@ static inline void dlci_put(struct gsm_dlci *dlci)
tty_port_put(&dlci->port);
}
+/**
+ * gsm_dlci_open_get - look up a DLCI and take a reference
+ * @gsm: GSM mux
+ * @addr: DLCI address
+ *
+ * Look up gsm->dlci[addr] under gsm->mutex and take a reference. Returns
+ * NULL if not present. Release with gsm_dlci_unget().
+ */
+static struct gsm_dlci *gsm_dlci_open_get(struct gsm_mux *gsm, unsigned int addr)
+{
+ struct gsm_dlci *dlci;
+
+ mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[addr];
+ if (dlci != NULL)
+ dlci_get(dlci);
+ mutex_unlock(&gsm->mutex);
+ return dlci;
+}
+
+/**
+ * gsm_dlci_unget - drop a reference from gsm_dlci_open_get()
+ * @dlci: DLCI to release
+ */
+static void gsm_dlci_unget(struct gsm_dlci *dlci)
+{
+ dlci_put(dlci);
+}
+
static void gsm_destroy_network(struct gsm_dlci *dlci);
/**
@@ -2839,11 +2890,21 @@ static void gsm_queue(struct gsm_mux *gsm)
case UI|PF:
case UIH:
case UIH|PF:
+ /*
+ * Pin the DLCI so gsm_cleanup_mux() cannot free it during
+ * dispatch. The mutex is dropped before dlci->data().
+ */
+ mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[address];
if (dlci == NULL || dlci->state != DLCI_OPEN) {
+ mutex_unlock(&gsm->mutex);
gsm_response(gsm, address, DM|PF);
return;
}
+ dlci_get(dlci);
+ mutex_unlock(&gsm->mutex);
dlci->data(dlci, gsm->buf, gsm->len);
+ dlci_put(dlci);
break;
default:
goto invalid;
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Weiming Shi @ 2026-06-20 16:56 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi
The receive worker walks gsm->dlci[] without gsm->mutex while a
concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
control handlers can dereference a freed gsm_dlci. v1's NULL check only
narrowed the window; this series fixes the use-after-free itself by
pinning each DLCI the dispatch dereferences with its existing tty_port
reference (dlci_get/put), so the data path stays lock-free.
v3:
- Drop the cmpxchg() in gsm_dlci_free(); the pin alone fixes the UAF (Greg).
- Keep the addr bounds check at each call site, not in the helper (Daniel).
- Correct the Fixes: tag to the refcount commit (Daniel).
- Add the AI-assist tag to patch 1 and trim the comments (Daniel).
Verification (KASAN, panic_on_warn=1): a reproducer targeting the MSC
handler crashes the unpatched kernel and survives 200+ race rounds on
this series. The selftest passes on both the clean and patched kernel
(pass:3 fail:0 skip:0).
Weiming Shi (2):
tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
selftests: tty: add base regression test for n_gsm line discipline
drivers/tty/n_gsm.c | 73 +++-
tools/testing/selftests/tty/.gitignore | 1 +
tools/testing/selftests/tty/Makefile | 2 +-
tools/testing/selftests/tty/config | 1 +
tools/testing/selftests/tty/tty_n_gsm_test.c | 344 +++++++++++++++++++
5 files changed, 414 insertions(+), 7 deletions(-)
create mode 100644 tools/testing/selftests/tty/tty_n_gsm_test.c
--
2.43.0
^ permalink raw reply
* RE: [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Starke, Daniel @ 2026-06-19 7:13 UTC (permalink / raw)
To: Weiming Shi
Cc: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan, Xiang Mei,
linux-serial@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CANgPUi24wvQ4CLMozb3EBAC-5QKWiMHWpoCQgsBHkG+vZjHALg@mail.gmail.com>
> > > The receive worker walks gsm->dlci[] without gsm->mutex while a
> > > concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
> > > control handlers can dereference a freed gsm_dlci. v1's NULL check only
> > > narrowed the window; v2 fixes the use-after-free itself.
> > >
> > > The fix pins each DLCI the dispatch dereferences with its existing
> > > tty_port reference (option 2), so the data path stays lock-free. See the
> > > patch 1 commit message for details, including why the late destructor
> > > uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
> > > concern).
> > >
> > > Changes since v1:
> > > - Fix the UAF by reference-pinning instead of a NULL check in the
> > > handlers; no gsm->mutex in the data path (Greg, Daniel).
> > > - Pin every DLCI the dispatch touches, not just the addressed one:
> > > MSC/RLS/PN operate on gsm->dlci[k] named in the payload.
> > > - Add a base selftest (patch 2), as Greg asked.
> > >
> > > Verification (KASAN, panic_on_warn=1): the originally reported splat is
> > > the gsm_control_reply() / CMD_TEST path (see the Link in patch 1). A
> > > reproducer targeting the MSC handler crashes the unpatched kernel and
> > > survives 270 race rounds on v2. The selftest passes on both the clean
> > > and patched kernel (pass:3 fail:0 skip:0).
> > >
> > > Weiming Shi (2):
> > > tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
> > > selftests: tty: add base regression test for n_gsm line discipline
> >
> > So now there is a race on device node level. We have the old virtual
> > gsmttys still waiting for the current pending operations to finish while
> > the reconfiguration of the ldisc triggers a recreation of these. How is
> > this handled?
> >
> A pending gsmtty operation stays bound to the old object. gsmtty_install()
> takes a dlci_get() and the gsmtty ops use tty->driver_data, not gsm->dlci[],
> so an open fd keeps its own reference and never reaches the recreated dlci
> (a fresh gsm_dlci_alloc()). On teardown gsm_dlci_release() does
> tty_vhangup(), which unblocks the pending ops, and sets DLCI_CLOSED, which
> every gsmtty op checks first.
>
> This is the existing tty_port refcount, and the receive path here uses the
> same dlci_get/put, so I don't think the pin adds a device-node race. But
> you know this hardware better than I do; if there's a path I'm missing,
> point me at it.
Sounds right. Thank you for the explanation. My tty internals understanding
is rather shallow.
> > PATCH 1/2:
> >
> > > - if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
> > > + if (addr == 0)
> > > return;
> > > - dlci = gsm->dlci[addr];
> >
> > Control octets can be transmitted on non-control DLCIs in convergence layer
> > type 2. You do not guard against invalid DLCIs anymore. Same for parameter
> > negotiation and RLS.
> >
>
> The checks aren't dropped, just folded into gsm_dlci_open_get(), which
> returns NULL for addr >= NUM_DLCI and for an empty slot. But hiding them
> in the lookup makes the diff read like the guard is gone, which was a bad
> call. For v4, maybe we should keep the addr checks at the call sites and
> et the helper only do the locked lookup and pin, so the guard stays
> visible where the DLCI is used? Does that match what you'd expect?
Let's revisit the code for gsm_control_modem for example:
len = gsm_read_ea_val(&addr, data, cl);
if (len < 1)
return;
addr >>= 1;
/* Closed port, or invalid ? */
if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
return;
dlci = gsm->dlci[addr];
Without the addr >= NUM_DLCI part you access the dlci array at a possible
out of bounds index if the received data was broken. Let us keep input data
validation at system boundaries. You also risk dereferencing a null
pointer if the requested DLCI has not been allocated, i.e. opened, yet.
Hence, both checks should be kept in place.
Best regards,
Daniel Starke
^ permalink raw reply
* Re: [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Weiming Shi @ 2026-06-18 16:39 UTC (permalink / raw)
To: Starke, Daniel
Cc: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan, Xiang Mei,
linux-serial@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <DU0PR10MB538744C92335756B7F125867E0E42@DU0PR10MB5387.EURPRD10.PROD.OUTLOOK.COM>
Starke, Daniel <daniel.starke@siemens.com> 于2026年6月17日周三 15:26写道:
>
> > The receive worker walks gsm->dlci[] without gsm->mutex while a
> > concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
> > control handlers can dereference a freed gsm_dlci. v1's NULL check only
> > narrowed the window; v2 fixes the use-after-free itself.
> >
> > The fix pins each DLCI the dispatch dereferences with its existing
> > tty_port reference (option 2), so the data path stays lock-free. See the
> > patch 1 commit message for details, including why the late destructor
> > uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
> > concern).
> >
> > Changes since v1:
> > - Fix the UAF by reference-pinning instead of a NULL check in the
> > handlers; no gsm->mutex in the data path (Greg, Daniel).
> > - Pin every DLCI the dispatch touches, not just the addressed one:
> > MSC/RLS/PN operate on gsm->dlci[k] named in the payload.
> > - Add a base selftest (patch 2), as Greg asked.
> >
> > Verification (KASAN, panic_on_warn=1): the originally reported splat is
> > the gsm_control_reply() / CMD_TEST path (see the Link in patch 1). A
> > reproducer targeting the MSC handler crashes the unpatched kernel and
> > survives 270 race rounds on v2. The selftest passes on both the clean
> > and patched kernel (pass:3 fail:0 skip:0).
> >
> > Weiming Shi (2):
> > tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
> > selftests: tty: add base regression test for n_gsm line discipline
>
> So now there is a race on device node level. We have the old virtual
> gsmttys still waiting for the current pending operations to finish while
> the reconfiguration of the ldisc triggers a recreation of these. How is
> this handled?
>
A pending gsmtty operation stays bound to the old object. gsmtty_install()
takes a dlci_get() and the gsmtty ops use tty->driver_data, not gsm->dlci[],
so an open fd keeps its own reference and never reaches the recreated dlci
(a fresh gsm_dlci_alloc()). On teardown gsm_dlci_release() does
tty_vhangup(), which unblocks the pending ops, and sets DLCI_CLOSED, which
every gsmtty op checks first.
This is the existing tty_port refcount, and the receive path here uses the
same dlci_get/put, so I don't think the pin adds a device-node race. But
you know this hardware better than I do; if there's a path I'm missing,
point me at it.
> PATCH 1/2:
>
> > - if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
> > + if (addr == 0)
> > return;
> > - dlci = gsm->dlci[addr];
>
> Control octets can be transmitted on non-control DLCIs in convergence layer
> type 2. You do not guard against invalid DLCIs anymore. Same for parameter
> negotiation and RLS.
>
The checks aren't dropped, just folded into gsm_dlci_open_get(), which
returns NULL for addr >= NUM_DLCI and for an empty slot. But hiding them
in the lookup makes the diff read like the guard is gone, which was a bad
call. For v4, maybe we should keep the addr checks at the call sites and
et the helper only do the locked lookup and pin, so the guard stays
visible where the DLCI is used? Does that match what you'd expect?
> > Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
> > Cc: stable@vger.kernel.org
> > Reported-by: Xiang Mei <xmei5@asu.edu>
> > Link: https://lore.kernel.org/all/DJ7OKN8EMAK8.22CE0B8NZXD73@gmail.com/
> > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
>
> This whole worker separation was added later, not in e1eaea46bb40. Maybe
> worth updating to the corresponding commit.
I'll find the commit that moved the eceive side onto the worker and
point Fixes: at that.
> Also, the code comments have a strong AI flavor but AI use was only
> disclosed for PATCH 2/2.
Sorry, I missed that tag. v4 will add
Thanks for the careful review.
>
> Best regards,
> Daniel Starke
^ permalink raw reply
* Re: [PATCH v2] serial: max310x: implement gpio_chip::get_direction()
From: Hugo Villeneuve @ 2026-06-18 14:56 UTC (permalink / raw)
To: Tapio Reijonen
Cc: Greg Kroah-Hartman, Jiri Slaby, Linus Walleij,
Bartosz Golaszewski, Alexander Shiyan, linux-kernel, linux-serial,
linux-gpio
In-Reply-To: <20260615-b4-serial-max310x-gpio-get-direction-v2-1-4704ba2b181a@vaisala.com>
On Mon, 15 Jun 2026 06:38:40 +0000
Tapio Reijonen <tapio.reijonen@vaisala.com> wrote:
> It's strongly recommended for GPIO drivers to always implement the
> .get_direction() callback - even when the direction is tracked in
> software. The GPIO core emits a warning when the callback is missing
> and a user reads the direction of a line, e.g. via
> /sys/kernel/debug/gpio.
>
> The MAX310X keeps the GPIO direction in the GPIOCFG register (a set bit
> selects output), which the existing direction_input/output callbacks
> already program, so the current direction can be read back directly.
>
> Fixes: f65444187a66 ("serial: New serial driver MAX310X")
> Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
> ---
> Found and HW-tested on an i.MX6 SoloX board with a MAX14830 over SPI:
> without this, "cat /sys/kernel/debug/gpio" triggers the gpiolib.c:429
> WARNING (tainting the kernel W) on each queried MAX14830 line; with it
> applied the lines report their in/out direction and the WARNING is gone.
> ---
> Changes in v2:
> - Address Hugo Villeneuve's review: use BIT(offset % 4) and put the
> return statement on a single line.
> - Rebase onto v7.1-rc7.
> - Link to v1: https://lore.kernel.org/r/20260602-b4-serial-max310x-gpio-get-direction-v1-1-23bf84e8ee14@vaisala.com
> ---
Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> drivers/tty/serial/max310x.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
> index ac7d3f197c3a5ce3531d5607f48e21a807314021..09b9ab57d2b4479da90fba178b093008f4b57bb9 100644
> --- a/drivers/tty/serial/max310x.c
> +++ b/drivers/tty/serial/max310x.c
> @@ -1212,6 +1212,17 @@ static int max310x_gpio_set(struct gpio_chip *chip, unsigned int offset,
> return 0;
> }
>
> +static int max310x_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
> +{
> + struct max310x_port *s = gpiochip_get_data(chip);
> + struct uart_port *port = &s->p[offset / 4].port;
> + unsigned int val;
> +
> + val = max310x_port_read(port, MAX310X_GPIOCFG_REG);
> +
> + return val & BIT(offset % 4) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
> +}
> +
> static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
> {
> struct max310x_port *s = gpiochip_get_data(chip);
> @@ -1421,6 +1432,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
> s->gpio.owner = THIS_MODULE;
> s->gpio.parent = dev;
> s->gpio.label = devtype->name;
> + s->gpio.get_direction = max310x_gpio_get_direction;
> s->gpio.direction_input = max310x_gpio_direction_input;
> s->gpio.get = max310x_gpio_get;
> s->gpio.direction_output= max310x_gpio_direction_output;
>
> ---
> base-commit: 4549871118cf616eecdd2d939f78e3b9e1dddc48
> change-id: 20260602-b4-serial-max310x-gpio-get-direction-b10ee5be4f24
>
> Best regards,
> --
> Tapio Reijonen <tapio.reijonen@vaisala.com>
>
>
--
Hugo Villeneuve
^ permalink raw reply
* Re: [PATCH v5 1/2] serial: qcom-geni: trace: Drop redundant len field from geni_serial_data
From: Konrad Dybcio @ 2026-06-18 8:55 UTC (permalink / raw)
To: Praveen Talari, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-kernel, linux-trace-kernel, linux-arm-msm, linux-serial,
mukesh.savaliya, aniket.randive, chandana.chiluveru
In-Reply-To: <20260615-add-tracepoints-for-qcom-geni-serial-v5-1-2efa4c97e0e2@oss.qualcomm.com>
On 6/15/26 4:16 PM, Praveen Talari wrote:
> The dynamic array stored in the ring buffer already carries its own
> length in the array metadata. There is no need to also store it as a
> separate scalar field in the entry struct.
>
> Drop __field(unsigned int, len) and the corresponding __entry->len
> assignment, and use __get_dynamic_array_len(data) in the TP_printk for
> both the len=%u format argument and the __print_hex() size argument.
> This saves 4 bytes per event on the ring buffer.
>
> Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
> ---
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH v3] scsi: ufs: sysfs: Add HS_GEAR6 string in power_info/gear sysfs output
From: Himanshu Batra @ 2026-06-18 3:05 UTC (permalink / raw)
To: Bart Van Assche
Cc: Alim Akhtar, Avri Altman, James E.J. Bottomley,
Martin K. Petersen, linux-scsi, linux-kernel, linux-serial,
vamshigajjela, manugautam
In-Reply-To: <c040d167-8747-43f7-ac30-2f5c5bcfbc02@acm.org>
On Tue, Jun 16, 2026 at 7:07 PM Bart Van Assche <bvanassche@acm.org> wrote:
>
> On 6/16/26 3:01 AM, Himanshu Batra wrote:
> > In power_info/gear sysfs, currently it supports output only till gear 5.
> > If operating mode is gear 6, it outputs "UNKNOWN".
> > Add support for HS_GEAR6 string in sysfs output when operating mode
> > is gear 6.
>
> Some general advice:
> - New versions of a patch should be posted as a new email thread instead
> of as a reply to an existing email conversation. Replies to an
> existing email conversation tend to get overlooked.
> - At least 24 hours should elapse before a new version of a patch is
> posted. Otherwise reviewers who are in another time zone don't have
> the chance to reply. For large patch series, more time should elapse
> between reposts (e.g. one week).
> - The "scsi:" prefix is no longer used for UFS kernel patches.
Acked, I will follow this for future contributions.
>
> Since the code changes look good to me:
>
> Reviewed-by: Bart Van Assche <bvanassche@acm.org>
>
^ permalink raw reply
* Re: [PATCH v2 6/6] MAINTAINERS: Add self for the sb1250-duart serial driver
From: Philippe Mathieu-Daudé @ 2026-06-17 12:01 UTC (permalink / raw)
To: Maciej W. Rozycki, Thomas Bogendoerfer, Greg Kroah-Hartman,
Jiri Slaby
Cc: Elena Reshetova, David Windsor, Kees Cook, Hans Liljestrand,
linux-mips, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605241637170.1450@angie.orcam.me.uk>
On 25/5/26 01:12, Maciej W. Rozycki wrote:
> I wrote this driver and seem to have been the main remaining user now.
>
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> ---
> New change in v2.
> ---
> MAINTAINERS | 5 +++++
> 1 file changed, 5 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 5/6] serial: sb1250-duart: Switch to spinlock protection for shared resource
From: Philippe Mathieu-Daudé @ 2026-06-17 12:01 UTC (permalink / raw)
To: Maciej W. Rozycki, Thomas Bogendoerfer, Greg Kroah-Hartman,
Jiri Slaby
Cc: Elena Reshetova, David Windsor, Kees Cook, Hans Liljestrand,
linux-mips, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605241630370.1450@angie.orcam.me.uk>
On 25/5/26 01:12, Maciej W. Rozycki wrote:
> The control register block is shared between DUART channels and so its
> resource has to be requested by the first channel claimed and released
> by the last one dropped.
>
> It is currently handled with an atomic counter, which however does not
> protect against a situation where request_mem_region() has failed, but
> another CPU has seen the map guard nonzero and refrained from calling
> this function for another channel where it should have (and likely also
> fail). This parallel execution scenario can in principle be arranged
> via the TIOCSSERIAL ioctl.
>
> Switch to using an ordinary counter then and spinlock protection for the
> counter updates along with the corresponding resource request/release
> calls, so that the case described above is covered.
>
> Fixes: b45d52797432 ("sb1250-duart.c: SB1250 DUART serial support")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> ---
> New change in v2.
> ---
> drivers/tty/serial/sb1250-duart.c | 28 ++++++++++++++++++----------
> 1 file changed, 18 insertions(+), 10 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 4/6] Revert "drivers: convert sbd_duart.map_guard from atomic_t to refcount_t"
From: Philippe Mathieu-Daudé @ 2026-06-17 11:59 UTC (permalink / raw)
To: Maciej W. Rozycki, Thomas Bogendoerfer, Greg Kroah-Hartman,
Jiri Slaby
Cc: Elena Reshetova, David Windsor, Kees Cook, Hans Liljestrand,
linux-mips, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605241628110.1450@angie.orcam.me.uk>
On 25/5/26 01:12, Maciej W. Rozycki wrote:
> Revert commit 22a33651a56f ("drivers: convert sbd_duart.map_guard from
> atomic_t to refcount_t"), which broke perfectly valid code:
>
> ------------[ cut here ]------------
> WARNING: CPU: 1 PID: 1 at lib/refcount.c:114 sbd_request_port+0x54/0x140
> refcount_t: increment on 0; use-after-free.
> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.11.0-rc2+ #34
> Stack : 0000000014001fe0 0000000000000000 ffffffff80830000 0000000000000000
> ffffffff8127bc7a ffffffff8016fe08 ffffffff808d0000 ffffffff808d0000
> ffffffff807aa828 ffffffff80822337 ffffffff808ce188 a8000001860b0000
> 0000000000000001 0000000000000001 00000000000001c8 ffffffff808a3090
> 00000000000000bb ffffffff801b09d4 a80000018609bb68 ffffffff801231cc
> ffffffff812a0000 ffffffff80171388 0000000000001000 ffffffff807aa828
> 0000000000000001 0000000000000001 0000000000000000 0000000000000000
> 0000000000000000 a80000018609bab0 0000000000000000 ffffffff803c47cc
> 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> ffffffff807cb648 ffffffff8010bff8 0000000014001fe1 ffffffff803c47cc
> ...
> Call Trace:
> [<ffffffff8010bff8>] show_stack+0x28/0x88
> [<ffffffff803c47cc>] dump_stack+0x8c/0xc0
> [<ffffffff801aff5c>] __warn+0xe0/0x114
> [<ffffffff801233f0>] warn_slowpath_fmt+0x40/0x50
> [<ffffffff80455bcc>] sbd_request_port+0x54/0x140
> [<ffffffff804563a4>] sbd_config_port+0x2c/0x68
> ---[ end trace f666d696412caa3e ]---
>
> (report at the offending commit) -- sbd_request_port() is called twice
> per DUART instance, to reserve a resource holding the control register
> block shared between the two channels, so there's no slightest chance
> for an overflow. Also this doesn't stop the driver from working and
> it's just the reservation that is missing as a result, i.e.:
>
> 10060100-100601ff : sb1250-duart
> 10060200-100602ff : sb1250-duart
>
> as from the offending change, vs:
>
> 10060100-100601ff : sb1250-duart
> 10060200-100602ff : sb1250-duart
> 10060300-100603ff : sb1250-duart
>
> beforehand, which is surely why the breakage has gone so long unnoticed.
>
> "If it ain't broke, don't fix it," so just revert the broken commit.
>
> Fixes: 22a33651a56f ("drivers: convert sbd_duart.map_guard from atomic_t to refcount_t")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> ---
> No change from v1 (4/4),
> <https://lore.kernel.org/r/alpine.DEB.2.21.2604130416440.29980@angie.orcam.me.uk/>.
> ---
> drivers/tty/serial/sb1250-duart.c | 20 ++++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 2/6] serial: sb1250-duart: Fix bootconsole handover lockup
From: Philippe Mathieu-Daudé @ 2026-06-17 11:56 UTC (permalink / raw)
To: Maciej W. Rozycki, Thomas Bogendoerfer, Greg Kroah-Hartman,
Jiri Slaby
Cc: Elena Reshetova, David Windsor, Kees Cook, Hans Liljestrand,
linux-mips, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605241623110.1450@angie.orcam.me.uk>
On 25/5/26 01:12, Maciej W. Rozycki wrote:
> Calling sbd_init_port() in the course of setting up the serial device
> causes line parameters to be messed up and the transmitter disabled.
> We've been lucky in that no message is usually produced to the kernel
> log between this call and the later call to uart_set_options() in the
> course of console setup done by sbd_serial_console_init(), or the system
> would hang as the console output handler in CFE tried to access a port
> whose transmitter has been disabled and line parameters messed up.
>
> It'll change with the next change to the driver, so fix sbd_init_port()
> such that line parameters are set for 115200n8 console operation as with
> the CFE firmware and the transmitter re-enabled after reset.
>
> Fixes: 84a9582fd203 ("serial: core: Start managing serial controllers to enable runtime PM")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Cc: stable@vger.kernel.org # v6.5+
> ---
> Changes from v1 (2/4),
> <https://lore.kernel.org/r/alpine.DEB.2.21.2604130338210.29980@angie.orcam.me.uk/>:
>
> - Sanitise the change heading.
> ---
> drivers/tty/serial/sb1250-duart.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 1/6] serial: sb1250-duart: Fix console message clobbering at channel resets
From: Philippe Mathieu-Daudé @ 2026-06-17 11:55 UTC (permalink / raw)
To: Maciej W. Rozycki, Thomas Bogendoerfer, Greg Kroah-Hartman,
Jiri Slaby
Cc: Elena Reshetova, David Windsor, Kees Cook, Hans Liljestrand,
linux-mips, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605241620470.1450@angie.orcam.me.uk>
On 25/5/26 01:12, Maciej W. Rozycki wrote:
> Ensure any characters outstanding have been sent before issuing channel
> resets so as to prevent messages issued to the bootconsole from getting
> clobbered.
>
> Contrary to device documentation at the time the transmitter empty bit
> is set only the transmit FIFO has been drained and there is still data
> outstanding in the transmitter shift register, so wait an extra amount
> of time for that register to drain too. This also prevents subsequent
> messages produced to the console from getting clobbered, owing to what
> seems a transmitter synchronisation issue.
>
> When called from sbd_serial_console_init() it is too early for fsleep()
> to work and even before lpj has been calculated and therefore the delay
> is actually not sufficient for the transmitter to drain and is merely a
> placeholder now. This will be addressed in a follow-up change.
>
> Fixes: 84a9582fd203 ("serial: core: Start managing serial controllers to enable runtime PM")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Cc: stable@vger.kernel.org # v6.5+
> ---
> Changes from v1 (1/4),
> <https://lore.kernel.org/r/alpine.DEB.2.21.2604130321540.29980@angie.orcam.me.uk/>:
>
> - Sanitise the change heading.
> ---
> drivers/tty/serial/sb1250-duart.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v1 1/1] serdev: acpi: Free resource list at appropriate time
From: Andy Shevchenko @ 2026-06-17 9:25 UTC (permalink / raw)
To: linux-serial, linux-kernel
Cc: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko
We do unneeded "double free" (emptying an empty list) in one case.
This is not a critical issue at all, the fix just makes code robust
against any possible future changes in the flow.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serdev/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index e9d044a331b0..7500efcdfc21 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -651,11 +651,11 @@ static int acpi_serdev_do_lookup(struct acpi_device *adev,
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
acpi_serdev_parse_resource, lookup);
- acpi_dev_free_resource_list(&resource_list);
-
if (ret < 0)
return -EINVAL;
+ acpi_dev_free_resource_list(&resource_list);
+
return 0;
}
--
2.50.1
^ permalink raw reply related
* RE: [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Starke, Daniel @ 2026-06-17 7:26 UTC (permalink / raw)
To: Weiming Shi, Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Xiang Mei, linux-serial@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260616173240.3665059-1-bestswngs@gmail.com>
> The receive worker walks gsm->dlci[] without gsm->mutex while a
> concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
> control handlers can dereference a freed gsm_dlci. v1's NULL check only
> narrowed the window; v2 fixes the use-after-free itself.
>
> The fix pins each DLCI the dispatch dereferences with its existing
> tty_port reference (option 2), so the data path stays lock-free. See the
> patch 1 commit message for details, including why the late destructor
> uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
> concern).
>
> Changes since v1:
> - Fix the UAF by reference-pinning instead of a NULL check in the
> handlers; no gsm->mutex in the data path (Greg, Daniel).
> - Pin every DLCI the dispatch touches, not just the addressed one:
> MSC/RLS/PN operate on gsm->dlci[k] named in the payload.
> - Add a base selftest (patch 2), as Greg asked.
>
> Verification (KASAN, panic_on_warn=1): the originally reported splat is
> the gsm_control_reply() / CMD_TEST path (see the Link in patch 1). A
> reproducer targeting the MSC handler crashes the unpatched kernel and
> survives 270 race rounds on v2. The selftest passes on both the clean
> and patched kernel (pass:3 fail:0 skip:0).
>
> Weiming Shi (2):
> tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
> selftests: tty: add base regression test for n_gsm line discipline
So now there is a race on device node level. We have the old virtual
gsmttys still waiting for the current pending operations to finish while
the reconfiguration of the ldisc triggers a recreation of these. How is
this handled?
PATCH 1/2:
> - if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
> + if (addr == 0)
> return;
> - dlci = gsm->dlci[addr];
Control octets can be transmitted on non-control DLCIs in convergence layer
type 2. You do not guard against invalid DLCIs anymore. Same for parameter
negotiation and RLS.
> Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
> Cc: stable@vger.kernel.org
> Reported-by: Xiang Mei <xmei5@asu.edu>
> Link: https://lore.kernel.org/all/DJ7OKN8EMAK8.22CE0B8NZXD73@gmail.com/
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
This whole worker separation was added later, not in e1eaea46bb40. Maybe
worth updating to the corresponding commit.
Also, the code comments have a strong AI flavor but AI use was only
disclosed for PATCH 2/2.
Best regards,
Daniel Starke
^ permalink raw reply
* Re: [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Weiming Shi @ 2026-06-17 5:54 UTC (permalink / raw)
To: Greg Kroah-Hartman, Weiming Shi
Cc: Jiri Slaby, Shuah Khan, Starke, Daniel, Xiang Mei, linux-serial,
linux-kselftest, linux-kernel
In-Reply-To: <2026061722-explode-predator-59f4@gregkh>
On Wed Jun 17, 2026 at 9:24 AM CST, Greg Kroah-Hartman wrote:
> On Tue, Jun 16, 2026 at 10:32:38AM -0700, Weiming Shi wrote:
>> The receive worker walks gsm->dlci[] without gsm->mutex while a
>> concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
>> control handlers can dereference a freed gsm_dlci. v1's NULL check only
>> narrowed the window; v2 fixes the use-after-free itself.
>>
>> The fix pins each DLCI the dispatch dereferences with its existing
>> tty_port reference (option 2), so the data path stays lock-free. See the
>> patch 1 commit message for details, including why the late destructor
>> uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
>> concern).
>
> Cool, but wow, that's complex for something that will never actually
> happen in a real device :)
>
> So do we want to add that complexity? if so, why?
>
> Ideally Daniel can verfiy this change is ok as they are the only known
> user here.
>
> And thanks for the test patch, but that's just a functional test, while
> great to have, and not one that can actually mimic a real device with
> its timing constraints, right?
>
> thanks,
>
> greg k-h
Hi,
The complexity is just the cmpxchg() in gsm_dlci_free(). The actual UAF fix
is only the tty_port pin (dlci_get/put) around the dispatch, which doesn't
touch any fast path. The cmpxchg() only guards the teardown+recreate case
Daniel mentioned, and isn't needed for the UAF.
So should I drop it and respin a v3 with the pin only? The use-after-free
is fully fixed either way.
Daniel, does the pin approach look right to you?
And yes, the test is functional only (pty bring-up/teardown, no timing).
It's the base regression test, not a race reproducer.
Thanks,
Weiming Shi
^ permalink raw reply
* Re: [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Greg Kroah-Hartman @ 2026-06-17 1:24 UTC (permalink / raw)
To: Weiming Shi
Cc: Jiri Slaby, Shuah Khan, Starke, Daniel, Xiang Mei, linux-serial,
linux-kselftest, linux-kernel
In-Reply-To: <20260616173240.3665059-1-bestswngs@gmail.com>
On Tue, Jun 16, 2026 at 10:32:38AM -0700, Weiming Shi wrote:
> The receive worker walks gsm->dlci[] without gsm->mutex while a
> concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
> control handlers can dereference a freed gsm_dlci. v1's NULL check only
> narrowed the window; v2 fixes the use-after-free itself.
>
> The fix pins each DLCI the dispatch dereferences with its existing
> tty_port reference (option 2), so the data path stays lock-free. See the
> patch 1 commit message for details, including why the late destructor
> uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
> concern).
Cool, but wow, that's complex for something that will never actually
happen in a real device :)
So do we want to add that complexity? if so, why?
Ideally Daniel can verfiy this change is ok as they are the only known
user here.
And thanks for the test patch, but that's just a functional test, while
great to have, and not one that can actually mimic a real device with
its timing constraints, right?
thanks,
greg k-h
^ permalink raw reply
* [PATCH v2 2/2] selftests: tty: add base regression test for n_gsm line discipline
From: Weiming Shi @ 2026-06-16 17:32 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi
In-Reply-To: <20260616173240.3665059-1-bestswngs@gmail.com>
n_gsm has no selftest coverage. Add a base functional regression test
that drives the line discipline over a local pty pair, so no real serial
hardware or modem is required, and exercises the GSM 07.10 / 3GPP TS 27.010
basic-option mux from userspace.
The test attaches N_GSM to the pty master, then:
- basic: brings up the mux (SETCONF, initiator side), drives the
DLCI 0 control channel SABM/UA handshake and tears it down.
- getconf: round-trips GSMIOC_GETCONF/GSMIOC_SETCONF and checks the
configuration is preserved.
- data_dlci: opens a data DLCI (DLCI 1) via the SABM/UA exchange and
verifies the responder side answers, covering the control
-> data DLCI path.
Frames are encoded by hand against 3GPP TS 27.010 (address EA/C-R/DLCI
bits, SABM/UA/UIH control fields, the reversed CRC-8 FCS) with the clause
numbers referenced in the comments, so the test doubles as a small,
readable description of the on-wire format.
It is a functional/regression test, not a race reproducer: it gives the
subsystem a green baseline to catch behavioural regressions, including in
the gsm_queue() control-frame dispatch path.
Wire it into the tty selftest Makefile, add CONFIG_N_GSM=y to the config
fragment, and ignore the built binary. The test SKIPs cleanly when N_GSM
is not built, /dev/ptmx is missing, or it lacks the capability to attach
the ldisc.
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
---
tools/testing/selftests/tty/.gitignore | 1 +
tools/testing/selftests/tty/Makefile | 2 +-
tools/testing/selftests/tty/config | 1 +
tools/testing/selftests/tty/tty_n_gsm_test.c | 344 +++++++++++++++++++
4 files changed, 347 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/tty/tty_n_gsm_test.c
diff --git a/tools/testing/selftests/tty/.gitignore b/tools/testing/selftests/tty/.gitignore
index 2453685d2..e3fcee15e 100644
--- a/tools/testing/selftests/tty/.gitignore
+++ b/tools/testing/selftests/tty/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
tty_tiocsti_test
tty_tstamp_update
+tty_n_gsm_test
diff --git a/tools/testing/selftests/tty/Makefile b/tools/testing/selftests/tty/Makefile
index 7f6fbe5a0..ae546d0d4 100644
--- a/tools/testing/selftests/tty/Makefile
+++ b/tools/testing/selftests/tty/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS = -O2 -Wall
-TEST_GEN_PROGS := tty_tstamp_update tty_tiocsti_test
+TEST_GEN_PROGS := tty_tstamp_update tty_tiocsti_test tty_n_gsm_test
LDLIBS += -lcap
include ../lib.mk
diff --git a/tools/testing/selftests/tty/config b/tools/testing/selftests/tty/config
index c6373aba6..66a5ffc9e 100644
--- a/tools/testing/selftests/tty/config
+++ b/tools/testing/selftests/tty/config
@@ -1 +1,2 @@
CONFIG_LEGACY_TIOCSTI=y
+CONFIG_N_GSM=y
diff --git a/tools/testing/selftests/tty/tty_n_gsm_test.c b/tools/testing/selftests/tty/tty_n_gsm_test.c
new file mode 100644
index 000000000..064231512
--- /dev/null
+++ b/tools/testing/selftests/tty/tty_n_gsm_test.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * n_gsm line discipline test
+ *
+ * Exercise the n_gsm (GSM 07.10 mux) control paths over a pty, so the driver
+ * can be regression-tested without the real modem hardware. The test attaches
+ * the ldisc, configures the mux, opens DLCI 0, drives a control frame through
+ * the receive path (reaching gsm_control_reply()) and reconfigures, which
+ * tears the mux down and frees the DLCI. It is a functional coverage test of
+ * the receive and teardown paths, not a reproducer for any specific race.
+ *
+ * The frame encoding follows 3GPP TS 07.10 (a.k.a. 27.010), basic option.
+ *
+ * Requires CONFIG_N_GSM and CAP_NET_ADMIN to attach the ldisc.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <time.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <linux/tty.h>
+#include <linux/gsmmux.h>
+
+#include "../kselftest_harness.h"
+
+#ifndef N_GSM0710
+#define N_GSM0710 21
+#endif
+
+/*
+ * GSM 07.10 basic option framing. Field encodings below are from
+ * 3GPP TS 07.10 (a.k.a. 27.010): the basic-option flag (section 5.2.6.1),
+ * the address field with EA/C-R/DLCI bits (5.2.1.2, command vs response
+ * C/R from table 1), the control field codings (5.2.1.3, table 2), the
+ * length field (5.2.1.5), and the control-channel message types (5.4.6.3).
+ */
+#define GSM0_SOF 0xf9 /* basic-option flag, 1001 1111 */
+#define ADDR_DLCI0 0x03 /* EA=1, C/R=1, DLCI=0 (command) */
+#define ADDR_DLCI0_RSP 0x01 /* EA=1, C/R=0, DLCI=0 (response) */
+#define ADDR_DLCI1 0x07 /* EA=1, C/R=1, DLCI=1 (command) */
+#define GSM_PF 0x10 /* poll/final bit */
+#define CTRL_SABM (0x2f | GSM_PF) /* SABM command */
+#define CTRL_UA (0x63 | GSM_PF) /* UA, the SABM acknowledgment */
+#define CTRL_UIH 0xef /* UIH command/response */
+#define INIT_FCS 0xff
+#define CMD_TEST_EA 0x23 /* (CMD_TEST << 1) | EA, type 5.4.6.3.4 */
+
+#define MAX_FRAME 64
+
+/* Reversed CRC-8 table (poly 0x07), from 3GPP TS 07.10 annex B.3.5. */
+static const unsigned char gsm_fcs8[256] = {
+0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf,
+};
+
+static unsigned char fcs_header(const unsigned char *p, int n)
+{
+ unsigned char fcs = INIT_FCS;
+ int i;
+
+ for (i = 0; i < n; i++)
+ fcs = gsm_fcs8[fcs ^ p[i]];
+ return 0xff - fcs;
+}
+
+/*
+ * Build a GSM0 frame: SOF addr ctrl len [data] FCS SOF.
+ * Returns the frame length, or -1 if it would not fit in MAX_FRAME.
+ */
+static int build_frame(unsigned char *out, unsigned char addr,
+ unsigned char ctrl, const unsigned char *data, int dlen)
+{
+ unsigned char hdr[3] = { addr, ctrl, (unsigned char)((dlen << 1) | 1) };
+ int i = 0, j;
+
+ if (dlen < 0 || dlen + 6 > MAX_FRAME)
+ return -1;
+
+ out[i++] = GSM0_SOF;
+ out[i++] = addr;
+ out[i++] = ctrl;
+ out[i++] = (unsigned char)((dlen << 1) | 1);
+ for (j = 0; j < dlen; j++)
+ out[i++] = data[j];
+ out[i++] = fcs_header(hdr, 3);
+ out[i++] = GSM0_SOF;
+ return i;
+}
+
+static int gsm_setconf(int fd, int mtu)
+{
+ struct gsm_config c;
+
+ memset(&c, 0, sizeof(c));
+ c.adaption = 1;
+ c.encapsulation = 0; /* basic option framing */
+ c.initiator = 0; /* responder: the peer (master side) drives DLCI 0 */
+ c.mru = 64;
+ c.mtu = mtu;
+ c.i = 1; /* UIH frames */
+ c.k = 2; /* window size */
+ /* Short timers and a single retry so open/close handshakes and the
+ * teardown complete quickly within the test.
+ */
+ c.t1 = 1;
+ c.t2 = 1;
+ c.n2 = 1;
+ return ioctl(fd, GSMIOC_SETCONF, &c);
+}
+
+/*
+ * Open a pty pair with a raw master and the n_gsm ldisc on the slave.
+ * Returns 0 and fills *mfd (master) / *sfd (slave/ldisc) on success, or
+ * -errno otherwise.
+ */
+static int gsm_open(int *mfd, int *sfd)
+{
+ int ldisc = N_GSM0710;
+ char sname[128];
+ struct termios tio;
+ int m, s, e;
+
+ m = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+ if (m < 0)
+ return -errno;
+ if (grantpt(m) || unlockpt(m) || ptsname_r(m, sname, sizeof(sname))) {
+ e = errno;
+ close(m);
+ return -e;
+ }
+ s = open(sname, O_RDWR | O_NOCTTY);
+ if (s < 0) {
+ e = errno;
+ close(m);
+ return -e;
+ }
+ if (tcgetattr(m, &tio) == 0) {
+ cfmakeraw(&tio);
+ tcsetattr(m, TCSANOW, &tio);
+ }
+ if (ioctl(s, TIOCSETD, &ldisc) < 0) {
+ e = errno;
+ close(s);
+ close(m);
+ return -e;
+ }
+ *mfd = m;
+ *sfd = s;
+ return 0;
+}
+
+static long now_ms(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+/*
+ * Wait until the mux sends a frame on DLCI 0 with the given address and
+ * control field, e.g. the UA that acknowledges SABM (addr 0x03), or the
+ * CMD_TEST reply (response addr 0x01). Returns 1 if a matching frame header
+ * (SOF, addr, ctrl) is seen, 0 on timeout. Matching the SOF + address +
+ * control sequence (rather than a lone control byte) avoids false hits on
+ * FCS or payload bytes that happen to equal the control value.
+ */
+static int wait_for_frame(int mfd, unsigned char addr, unsigned char ctrl,
+ int timeout_ms)
+{
+ struct pollfd pfd = { .fd = mfd, .events = POLLIN };
+ long deadline = now_ms() + timeout_ms;
+ unsigned char buf[256];
+ int left;
+
+ while ((left = deadline - now_ms()) > 0) {
+ int ret, n, i;
+
+ ret = poll(&pfd, 1, left);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ return 0;
+ }
+ if (ret == 0 || !(pfd.revents & POLLIN))
+ continue;
+
+ n = read(mfd, buf, sizeof(buf));
+ if (n <= 0)
+ continue;
+ for (i = 0; i + 2 < n; i++) {
+ if (buf[i] == GSM0_SOF && buf[i + 1] == addr &&
+ buf[i + 2] == ctrl)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+FIXTURE(n_gsm)
+{
+ int mfd; /* pty master */
+ int sfd; /* pty slave, carrying the n_gsm ldisc */
+};
+
+FIXTURE_SETUP(n_gsm)
+{
+ int ret;
+
+ /* So FIXTURE_TEARDOWN does not close fd 0 if setup bails early. */
+ self->mfd = -1;
+ self->sfd = -1;
+
+ ret = gsm_open(&self->mfd, &self->sfd);
+
+ if (ret == -EPERM || ret == -EACCES)
+ SKIP(return, "need CAP_NET_ADMIN to attach n_gsm ldisc");
+ if (ret == -EINVAL || ret == -ENODEV)
+ SKIP(return, "CONFIG_N_GSM not enabled");
+ if (ret == -ENOENT)
+ SKIP(return, "no pty support (/dev/ptmx missing)");
+ ASSERT_EQ(ret, 0)
+ TH_LOG("gsm_open failed: %d", ret);
+}
+
+FIXTURE_TEARDOWN(n_gsm)
+{
+ if (self->sfd >= 0)
+ close(self->sfd);
+ if (self->mfd >= 0)
+ close(self->mfd);
+}
+
+/*
+ * Configure the mux, open DLCI 0 and push a control frame through the receive
+ * path, then reconfigure to tear the mux down. This needs no hardware and
+ * verifies the n_gsm receive/teardown paths are reachable and do not crash.
+ */
+TEST_F(n_gsm, basic)
+{
+ unsigned char sabm[MAX_FRAME], cmd_test[MAX_FRAME];
+ /*
+ * CMD_TEST control command: cmd byte = (CMD_TEST << 1) | EA, then a
+ * length-EA byte (0x01) meaning zero bytes of test data.
+ */
+ unsigned char payload[2] = { CMD_TEST_EA, 0x01 };
+ int slen, tlen;
+
+ /* Activate the mux; this allocates DLCI 0. */
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ slen = build_frame(sabm, ADDR_DLCI0, CTRL_SABM, NULL, 0);
+ tlen = build_frame(cmd_test, ADDR_DLCI0, CTRL_UIH, payload, sizeof(payload));
+ ASSERT_GT(slen, 0);
+ ASSERT_GT(tlen, 0);
+
+ /* Open DLCI 0 and wait for the UA reply confirming it reached OPEN. */
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ ASSERT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 0 did not open (no UA reply)");
+
+ /*
+ * Drive a CMD_TEST control frame; the receive path reaches
+ * gsm_control_reply(), which sends a CMD_TEST reply back on the
+ * response address. Wait for that reply so we know the frame was
+ * processed, rather than sleeping.
+ */
+ ASSERT_EQ(write(self->mfd, cmd_test, tlen), tlen);
+ EXPECT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0_RSP, CTRL_UIH, 1000), 1)
+ TH_LOG("no CMD_TEST reply seen");
+
+ /* Reconfigure: tears the mux down and frees DLCI 0. */
+ EXPECT_EQ(gsm_setconf(self->sfd, 127), 0);
+}
+
+/*
+ * Configure the mux and read the configuration back with GSMIOC_GETCONF,
+ * checking the value round-trips.
+ */
+TEST_F(n_gsm, getconf)
+{
+ struct gsm_config c;
+
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ memset(&c, 0, sizeof(c));
+ ASSERT_EQ(ioctl(self->sfd, GSMIOC_GETCONF, &c), 0)
+ TH_LOG("GSMIOC_GETCONF failed: %m");
+ EXPECT_EQ(c.mtu, 64u);
+}
+
+/*
+ * Open DLCI 0, then open a data channel (DLCI 1) with SABM and check the mux
+ * acknowledges it with a UA. This exercises gsm_dlci_alloc() and the data DLCI
+ * open path, not just the control channel.
+ */
+TEST_F(n_gsm, data_dlci)
+{
+ unsigned char sabm[MAX_FRAME];
+ int slen;
+
+ ASSERT_EQ(gsm_setconf(self->sfd, 64), 0)
+ TH_LOG("GSMIOC_SETCONF failed: %m");
+
+ slen = build_frame(sabm, ADDR_DLCI0, CTRL_SABM, NULL, 0);
+ ASSERT_GT(slen, 0);
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ ASSERT_EQ(wait_for_frame(self->mfd, ADDR_DLCI0, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 0 did not open");
+
+ /* Open DLCI 1 (a data channel) and wait for its UA. */
+ slen = build_frame(sabm, ADDR_DLCI1, CTRL_SABM, NULL, 0);
+ ASSERT_GT(slen, 0);
+ ASSERT_EQ(write(self->mfd, sabm, slen), slen);
+ EXPECT_EQ(wait_for_frame(self->mfd, ADDR_DLCI1, CTRL_UA, 1000), 1)
+ TH_LOG("DLCI 1 did not open (no UA reply)");
+
+ /* Tear the mux down. */
+ EXPECT_EQ(gsm_setconf(self->sfd, 127), 0);
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
From: Weiming Shi @ 2026-06-16 17:32 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi, stable
In-Reply-To: <20260616173240.3665059-1-bestswngs@gmail.com>
The receive worker (flush_to_ldisc -> gsmld_receive_buf -> gsm0_receive/
gsm1_receive -> gsm_queue) reads gsm->dlci[address] and dispatches the
frame via dlci->data() without holding gsm->mutex. The control handlers
reached through dlci->data() then re-read gsm->dlci[]: gsm_control_reply()
re-reads gsm->dlci[0], while gsm_control_modem() (MSC), gsm_control_rls()
(RLS) and gsm_control_negotiation() (PN) re-read gsm->dlci[addr] for the
DLCI named in the command - a different channel from the one the frame
was addressed to.
Concurrently GSMIOC_SETCONF -> gsm_config() -> gsm_cleanup_mux() takes
gsm->mutex and releases every DLCI via gsm_dlci_release() -> dlci_put().
When the last reference is dropped the destructor gsm_dlci_free() clears
gsm->dlci[addr] and frees the object. If the worker dereferences one of
those DLCIs while it is being freed, it touches freed memory.
A peer that drives DLCI 0 control frames (e.g. CMD_TEST) while the mux
owner reconfigures the line discipline with GSMIOC_SETCONF can therefore
trigger a use-after-free:
BUG: KASAN: slab-use-after-free in gsm_control_reply.isra.0
Read of size 8 at addr ffff888029ae9000 by task kworker/u16:2/46
Workqueue: events_unbound flush_to_ldisc
Call Trace:
gsm_control_reply.isra.0 (drivers/tty/n_gsm.c:1494)
gsm_dlci_command (drivers/tty/n_gsm.c:2477)
gsmld_receive_buf (drivers/tty/n_gsm.c:3616)
tty_ldisc_receive_buf (drivers/tty/tty_buffer.c:398)
tty_port_default_receive_buf (drivers/tty/tty_port.c:37)
flush_to_ldisc (drivers/tty/tty_buffer.c:502)
process_one_work
worker_thread
kthread
Freed by task 5110:
kfree
gsm_cleanup_mux (drivers/tty/n_gsm.c:3161)
gsmld_ioctl (drivers/tty/n_gsm.c:3415)
tty_ioctl
Pin each DLCI across the dereference with its existing tty_port reference.
gsm_dlci_open_get() looks gsm->dlci[addr] up under gsm->mutex and, if
present, takes a dlci_get() reference before dropping the mutex; the
caller releases it with gsm_dlci_unget() once it is done. While the
reference is held the kref cannot reach zero, so gsm_dlci_free() cannot
run: the object stays live and gsm->dlci[addr] is not cleared. gsm_queue()
pins the addressed DLCI for the UI/UIH dispatch, and gsm_control_modem(),
gsm_control_rls() and gsm_control_negotiation() each pin the DLCI they
operate on.
The reference is taken only under the mutex, around the lookup; the mutex
is released before dlci->data() and before the data-path work
(gsm_process_modem(), tty_flip_buffer_push(), gsm_data_queue(), ...), so
the receive/transmit path is not serialised by gsm->mutex and its timing
is unaffected.
Because a pinned DLCI can outlive the gsm_cleanup_mux() that released it,
a subsequent GSMIOC_SETCONF may re-create a DLCI at the same address
before the worker drops its reference. Make gsm_dlci_free() clear the
slot only if it still points at the DLCI being freed, so the late
destructor cannot wipe a freshly installed DLCI:
cmpxchg(&dlci->gsm->dlci[dlci->addr], dlci, NULL);
Attaching the n_gsm line discipline requires CAP_NET_ADMIN (gsmld_open()
uses capable(), not ns_capable()), so this is a local denial of service
for a privileged mux owner whose control channel is driven by an
untrusted peer on the serial link while it reconfigures; harden the
receive path regardless.
Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
Cc: stable@vger.kernel.org
Reported-by: Xiang Mei <xmei5@asu.edu>
Link: https://lore.kernel.org/all/DJ7OKN8EMAK8.22CE0B8NZXD73@gmail.com/
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
drivers/tty/n_gsm.c | 105 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 96 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c13e050de..e1ab3a08f 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -453,6 +453,8 @@ static const u8 gsm_fcs8[256] = {
#define GOOD_FCS 0xCF
static void gsm_dlci_close(struct gsm_dlci *dlci);
+static struct gsm_dlci *gsm_dlci_open_get(struct gsm_mux *gsm, unsigned int addr);
+static void gsm_dlci_unget(struct gsm_dlci *dlci);
static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len);
static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk);
static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
@@ -1694,10 +1696,8 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
return;
addr >>= 1;
- /* Closed port, or invalid ? */
- if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
+ if (addr == 0)
return;
- dlci = gsm->dlci[addr];
/* Must be at least one byte following the EA */
if ((cl - len) < 1)
@@ -1711,12 +1711,23 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
if (len < 1)
return;
+ /*
+ * Pin the addressed DLCI across the dereference: a concurrent
+ * GSMIOC_SETCONF -> gsm_cleanup_mux() can free it otherwise. Pinning
+ * (not gsm->mutex over the whole handler) keeps the data path lock
+ * free.
+ */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL)
+ return;
+
tty = tty_port_tty_get(&dlci->port);
gsm_process_modem(tty, dlci, modem, cl);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
+ gsm_dlci_unget(dlci);
gsm_control_reply(gsm, CMD_MSC, data, clen);
}
@@ -1746,15 +1757,26 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
/* Invalid DLCI? */
params = (struct gsm_dlci_param_bits *)data;
addr = FIELD_GET(PN_D_FIELD_DLCI, params->d_bits);
- if (addr == 0 || addr >= NUM_DLCI || !gsm->dlci[addr]) {
+ if (addr == 0) {
+ gsm->open_error++;
+ return;
+ }
+
+ /*
+ * Pin the addressed DLCI across the negotiation; see gsm_control_modem()
+ * for why. Unlike MSC/RLS this DLCI need not be open, so pin first and
+ * check the state afterwards.
+ */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL) {
gsm->open_error++;
return;
}
- dlci = gsm->dlci[addr];
/* Too late for parameter negotiation? */
if ((!cr && dlci->state == DLCI_OPENING) || dlci->state == DLCI_OPEN) {
gsm->open_error++;
+ gsm_dlci_unget(dlci);
return;
}
@@ -1765,6 +1787,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
pr_info("%s PN failed\n", __func__);
gsm->open_error++;
gsm_dlci_close(dlci);
+ gsm_dlci_unget(dlci);
return;
}
@@ -1785,6 +1808,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
pr_info("%s PN in invalid state\n", __func__);
gsm->open_error++;
}
+ gsm_dlci_unget(dlci);
}
/**
@@ -1800,6 +1824,7 @@ static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr,
static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
{
+ struct gsm_dlci *dlci;
struct tty_port *port;
unsigned int addr = 0;
u8 bits;
@@ -1816,15 +1841,21 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
if (len <= 0)
return;
addr >>= 1;
- /* Closed port, or invalid ? */
- if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL)
+ if (addr == 0)
return;
/* No error ? */
bits = *dp;
if ((bits & 1) == 0)
return;
- port = &gsm->dlci[addr]->port;
+ /*
+ * Pin the addressed DLCI across the dereference; see gsm_control_modem()
+ * for why. gsm_cleanup_mux() can free it concurrently otherwise.
+ */
+ dlci = gsm_dlci_open_get(gsm, addr);
+ if (dlci == NULL)
+ return;
+ port = &dlci->port;
if (bits & 2)
tty_insert_flip_char(port, 0, TTY_OVERRUN);
@@ -1835,6 +1866,7 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
tty_flip_buffer_push(port);
+ gsm_dlci_unget(dlci);
gsm_control_reply(gsm, CMD_RLS, data, clen);
}
@@ -2694,7 +2726,14 @@ static void gsm_dlci_free(struct tty_port *port)
struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
timer_shutdown_sync(&dlci->t1);
- dlci->gsm->dlci[dlci->addr] = NULL;
+ /*
+ * Only clear the slot if it still points at us. A receive worker can
+ * pin this DLCI across gsm_queue() dispatch with dlci_get(); if a
+ * concurrent GSMIOC_SETCONF tears the mux down and re-creates a DLCI
+ * at the same address before the worker drops its reference, the slot
+ * already refers to the new DLCI and must not be cleared here.
+ */
+ cmpxchg(&dlci->gsm->dlci[dlci->addr], dlci, NULL);
kfifo_free(&dlci->fifo);
while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
dev_kfree_skb(dlci->skb);
@@ -2711,6 +2750,42 @@ static inline void dlci_put(struct gsm_dlci *dlci)
tty_port_put(&dlci->port);
}
+/**
+ * gsm_dlci_open_get - look up a DLCI and pin it
+ * @gsm: GSM mux
+ * @addr: DLCI address
+ *
+ * Look up gsm->dlci[addr] under gsm->mutex and, if present, take a
+ * tty_port reference so it cannot be freed while a control-frame handler
+ * dereferences it. A concurrent GSMIOC_SETCONF -> gsm_cleanup_mux()
+ * releases DLCIs under the same mutex, so the lookup and the pin are
+ * atomic with respect to the teardown. Returns the pinned DLCI or NULL.
+ * The caller must release it with gsm_dlci_unget(). Callers that require
+ * a particular state must check dlci->state themselves.
+ */
+static struct gsm_dlci *gsm_dlci_open_get(struct gsm_mux *gsm, unsigned int addr)
+{
+ struct gsm_dlci *dlci;
+
+ if (addr >= NUM_DLCI)
+ return NULL;
+ mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[addr];
+ if (dlci != NULL)
+ dlci_get(dlci);
+ mutex_unlock(&gsm->mutex);
+ return dlci;
+}
+
+/**
+ * gsm_dlci_unget - drop a reference from gsm_dlci_open_get()
+ * @dlci: DLCI to release
+ */
+static void gsm_dlci_unget(struct gsm_dlci *dlci)
+{
+ dlci_put(dlci);
+}
+
static void gsm_destroy_network(struct gsm_dlci *dlci);
/**
@@ -2839,11 +2914,23 @@ static void gsm_queue(struct gsm_mux *gsm)
case UI|PF:
case UIH:
case UIH|PF:
+ /*
+ * Pin the DLCI so a concurrent gsm_cleanup_mux() cannot free
+ * it while dlci->data() and the handlers it reaches use it.
+ * The mutex is dropped before the dispatch, so the data path
+ * is not serialised.
+ */
+ mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[address];
if (dlci == NULL || dlci->state != DLCI_OPEN) {
+ mutex_unlock(&gsm->mutex);
gsm_response(gsm, address, DM|PF);
return;
}
+ dlci_get(dlci);
+ mutex_unlock(&gsm->mutex);
dlci->data(dlci, gsm->buf, gsm->len);
+ dlci_put(dlci);
break;
default:
goto invalid;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/2] tty: n_gsm: fix gsm_queue() UAF and add a base regression test
From: Weiming Shi @ 2026-06-16 17:32 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Shuah Khan
Cc: Starke, Daniel, Xiang Mei, linux-serial, linux-kselftest,
linux-kernel, Weiming Shi
The receive worker walks gsm->dlci[] without gsm->mutex while a
concurrent GSMIOC_SETCONF -> gsm_cleanup_mux() frees the DLCIs, so the
control handlers can dereference a freed gsm_dlci. v1's NULL check only
narrowed the window; v2 fixes the use-after-free itself.
The fix pins each DLCI the dispatch dereferences with its existing
tty_port reference (option 2), so the data path stays lock-free. See the
patch 1 commit message for details, including why the late destructor
uses cmpxchg() so it cannot wipe a re-created mux (Daniel's teardown
concern).
Changes since v1:
- Fix the UAF by reference-pinning instead of a NULL check in the
handlers; no gsm->mutex in the data path (Greg, Daniel).
- Pin every DLCI the dispatch touches, not just the addressed one:
MSC/RLS/PN operate on gsm->dlci[k] named in the payload.
- Add a base selftest (patch 2), as Greg asked.
Verification (KASAN, panic_on_warn=1): the originally reported splat is
the gsm_control_reply() / CMD_TEST path (see the Link in patch 1). A
reproducer targeting the MSC handler crashes the unpatched kernel and
survives 270 race rounds on v2. The selftest passes on both the clean
and patched kernel (pass:3 fail:0 skip:0).
Weiming Shi (2):
tty: n_gsm: fix use-after-free in gsm_queue() control frame dispatch
selftests: tty: add base regression test for n_gsm line discipline
drivers/tty/n_gsm.c | 105 +++++-
tools/testing/selftests/tty/.gitignore | 1 +
tools/testing/selftests/tty/Makefile | 2 +-
tools/testing/selftests/tty/config | 1 +
tools/testing/selftests/tty/tty_n_gsm_test.c | 344 +++++++++++++++++++
5 files changed, 443 insertions(+), 10 deletions(-)
create mode 100644 tools/testing/selftests/tty/tty_n_gsm_test.c
--
2.43.0
^ permalink raw reply
* Re: [PATCH v3 2/3] dt-bindings: serial: maxim,max310x: describe per-channel rs485 subnodes
From: Rob Herring (Arm) @ 2026-06-16 17:28 UTC (permalink / raw)
To: Tapio Reijonen
Cc: linux-serial, Conor Dooley, Hugo Villeneuve, Jiri Slaby,
linux-kernel, Greg Kroah-Hartman, devicetree, Krzysztof Kozlowski
In-Reply-To: <20260615-b4-max310x-rs485-dt-v3-2-7e79f064bdd7@vaisala.com>
On Mon, 15 Jun 2026 10:27:36 +0000, Tapio Reijonen wrote:
> The MAX310x is a family of one- (max3107, max3108), two- (max3109) and
> four-channel (max14830) UARTs. The binding pulls in
> /schemas/serial/rs485.yaml at the chip level, describing a single set of
> RS-485 properties - enough for the single-channel parts, but a
> multi-channel chip can wire RS-485 differently on each channel.
>
> Split the binding per compatible:
>
> - single-channel parts (max3107, max3108): the chip node is itself the
> serial port and carries the RS-485 properties, as before;
>
> - multi-channel parts (max3109, max14830): the chip node is only a
> container and is no longer a serial node; each channel is a "serial@N"
> subnode that carries the standard serial.yaml/rs485.yaml properties
> (and may host a serial slave device). max3109 has channels 0-1,
> max14830 has 0-3.
>
> This avoids a chip node that is simultaneously a serial node and the
> parent of serial nodes. The driver still reads chip-level RS-485 for
> single-channel and legacy device trees, so existing users are unaffected.
>
> Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
> ---
> .../devicetree/bindings/serial/maxim,max310x.yaml | 92 +++++++++++++++++++++-
> 1 file changed, 90 insertions(+), 2 deletions(-)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v3] scsi: ufs: sysfs: Add HS_GEAR6 string in power_info/gear sysfs output
From: Bart Van Assche @ 2026-06-16 13:37 UTC (permalink / raw)
To: Himanshu Batra, Alim Akhtar, Avri Altman
Cc: James E.J. Bottomley, Martin K. Petersen, linux-scsi,
linux-kernel, linux-serial, vamshigajjela, manugautam
In-Reply-To: <20260616100121.548759-1-himanshubatra@google.com>
On 6/16/26 3:01 AM, Himanshu Batra wrote:
> In power_info/gear sysfs, currently it supports output only till gear 5.
> If operating mode is gear 6, it outputs "UNKNOWN".
> Add support for HS_GEAR6 string in sysfs output when operating mode
> is gear 6.
Some general advice:
- New versions of a patch should be posted as a new email thread instead
of as a reply to an existing email conversation. Replies to an
existing email conversation tend to get overlooked.
- At least 24 hours should elapse before a new version of a patch is
posted. Otherwise reviewers who are in another time zone don't have
the chance to reply. For large patch series, more time should elapse
between reposts (e.g. one week).
- The "scsi:" prefix is no longer used for UFS kernel patches.
Since the code changes look good to me:
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
^ permalink raw reply
* [PATCH v3] scsi: ufs: sysfs: Add HS_GEAR6 string in power_info/gear sysfs output
From: Himanshu Batra @ 2026-06-16 10:01 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche
Cc: James E.J. Bottomley, Martin K. Petersen, linux-scsi,
linux-kernel, linux-serial, vamshigajjela, manugautam,
Himanshu Batra
In-Reply-To: <2026061659-enjoyer-boogeyman-25c0@gregkh>
In power_info/gear sysfs, currently it supports output only till gear 5.
If operating mode is gear 6, it outputs "UNKNOWN".
Add support for HS_GEAR6 string in sysfs output when operating mode
is gear 6.
Signed-off-by: Himanshu Batra <himanshubatra@google.com>
---
Changes in v3:
- Fixed the identity alignment issue: updated both the 'From:' line
and 'Signed-off-by:' tag to use my full real name ("Himanshu Batra")
Changes in v2:
- A slightly better comment.
drivers/ufs/core/ufs-sysfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 99af3c73f1af..d1f5041fc3c8 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -54,6 +54,7 @@ static const char *ufs_hs_gear_to_string(enum ufs_hs_gear_tag gear)
case UFS_HS_G3: return "HS_GEAR3";
case UFS_HS_G4: return "HS_GEAR4";
case UFS_HS_G5: return "HS_GEAR5";
+ case UFS_HS_G6: return "HS_GEAR6";
default: return "UNKNOWN";
}
}
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox