Skip to contentSkip to conversation

soc: aspeed: Add BMC and host driver for PCIe BMC device

PATCH Superseded Grégoire Layet 6 participants 28 messages Jul 8 – Jul 14

Subsystems (3)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover soc: aspeed: Add BMC and host driver for PCIe BMC device

This is a v4 for upstreaming the VUART over PCIe BMC device driver. The initial driver is from the ASPEED kernel SDK (master-v6.18) [1].

There are two drivers: a BMC-side driver and a host-side driver. Together they enable host<->BMC VUART communication via PCIe.

The virtual UART is an 8250-compatible register set.
On the AST2600, two VUARTs can be exposed over PCI via the PCI BMC device.

The host cannot access the BMC's memory. Only the exposed features are accessible. These are the KCS4 channel and 2 VUARTs. There is also some mailbox register functionality for a communication between the host and the BMC. More information can be found here [2].

The v3 and this v4 mainly modifies the BMC driver and focuses on VUART. The BMC driver is now incorporated into the '8250_aspeed_vuart' driver. A specific flag can be set to indicate that the VUART should be used over PCI. Several changes have been made to the 8250 device tree binding and the 'aspeed-g6.dtsi'.

This v4 serves as a resend of the v3 while applying Krzysztof's review.

Changes since v3 [3]:
- Add the aspeed,ast2600-vuart compatible entry to the '8250' DT binding
- Add the aspeed,ast2600-vuart compatible property in 'aspeed-g6.dtsi'
- Add the aspeed,vuart-over-pci boolean property to the '8250' DT binding, only for the aspeed,ast2600-vuart
- Add the syscon phandle property required for aspeed,vuart-over-pci.
- Add the aspeed,vuart-over-pci flag and syscon phandle to the vuart3 and vuart4
- Cleanup the VUART over PCI code in the '8250_aspeed_vuart' driver.
- Further cleanup of the host side driver.

The host-side driver is still in /soc/aspeed/, as it is very specific to this SoC for me. I didn't receive any feedback on where to put this driver. I can, of course, change this to the relevant location.

It's important to consider that the host driver will do multiple functions. The AST2600 also supports LPC over PCI, with a specific KCS channel (KCS4). This driver should also be used to enable the IPMI automatically via this KCS channel. The UART and the IPMI will depend on the same PCI resource (BAR1), so this must be configured in one driver.

As with v3, VUART data flow and MSI interrupts have been verified working on the test hardware.

Tested on:
BMC:
- Asus IPMI Kommando Card R1.01, AST2600 A3.
- OpenBMC
Host:
- Linux kernel v7.0.0

This series only supports AST2600; the AST2700 is not supported.

Same as v3, I would like to know whether I should add the 'lpc-io-reg' and 'lpc-interrupt' values to the vuart3 and vuart4 nodes directly in the 'aspeed-g6.dtsi'. The host driver is not capable of finding the vuart address on its own, so they are hardcoded to 0x3f8 and 0x2f8. It will not work with other addresses, so perhaps they should be in the .dtsi to ensure the correct configuration for the 2 vuart over PCI.

For the interrupt number, my test is working with interrupt = 0 for vuart3 and interrupt = 1 for vuart4. I don't fully understand how the silicon routes MSI numbers to the VUART but the following combination is working :

       | host MSI idx | BMC lpc-interrupts |
VUART3 |      16      |       0            |
VUART4 |      17      |       1            |

The original ASPEED driver used MSI index 15 for the VUART4. I tested every lpc-interrupts on the BMC from 0 to 15, but none of them worked with the host MSI index set to 15.

For me, the silicon only routes the MSI index 16 to VUART3 and 17 to VUART4, and the lpc-interrupt needs to match the 4 least significant bits. I might be wrong on this explanation but the data path is working with those numbers. There is no explanation for any of this in the datasheet.

[1]: https://github.com/AspeedTech-BMC/linux/tree/aspeed-master-v6.18/drivers/soc/aspeed
[2]: https://lore.kernel.org/linux-aspeed/CAFi2wKYOAotiezepDqaR5PZDqDaPKKDfAEnpx5EHC0mL39hy6w@mail.gmail.com/
[3]: https://lore.kernel.org/linux-aspeed/[email protected]/

Grégoire Layet (7):
dt-bindings: serial: 8250: aspeed: add compatible string for ast2600
dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop
serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string
serial: 8250_aspeed_vuart: add VUART over PCI
soc: aspeed: add host-side PCIe BMC device driver
ARM: dts: aspeed: g6: Change vuart compatible string for ast2600
ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4

 .../devicetree/bindings/serial/8250.yaml      |  46 ++++-
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi       |  12 +-
 drivers/soc/aspeed/Kconfig                    |  15 ++
 drivers/soc/aspeed/Makefile                   |   1 +
 drivers/soc/aspeed/aspeed-host-bmc-dev.c      | 174 ++++++++++++++++++
 drivers/tty/serial/8250/8250_aspeed_vuart.c   |  87 +++++++++
 6 files changed, 323 insertions(+), 12 deletions(-)
 create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c

base-commit: 564edaca14861ba9e58d4e646d272c677296d285 --
2.54.0

#1 lore raw

PATCH v4 1/7 dt-bindings: serial: 8250: aspeed: add compatible string for ast2600

The ast2600 was using the ast2500 vuart compatible string. Make it possible to have ast2600-specific properties.

---
 .../devicetree/bindings/serial/8250.yaml      | 24 ++++++++++++-------
 1 file changed, 16 insertions(+), 8 deletions(-)
Documentation/devicetree/bindings/serial/8250.yaml +16 -8
index bb7b9c87a807..8f22121381fc 100644
@@ -23,7 +23,10 @@ allOf:
     then:
       properties:
         compatible:
-          const: aspeed,ast2500-vuart
+          contains:
+            enum:
+              - aspeed,ast2500-vuart
+              - aspeed,ast2600-vuart
   - if:
       properties:
         compatible:
@@ -106,6 +109,9 @@ properties:
       - const: ns16850
       - const: aspeed,ast2400-vuart
       - const: aspeed,ast2500-vuart
+      - items:
+          - const: aspeed,ast2600-vuart
+          - const: aspeed,ast2500-vuart
       - const: intel,xscale-uart
       - const: mrvl,pxa-uart
       - const: nuvoton,wpcm450-uart
@@ -287,17 +293,19 @@ properties:
   aspeed,sirq-polarity-sense:
     $ref: /schemas/types.yaml#/definitions/phandle-array
     description: |
-      Phandle to aspeed,ast2500-scu compatible syscon alongside register
-      offset and bit number to identify how the SIRQ polarity should be
-      configured. One possible data source is the LPC/eSPI mode bit. Only
-      applicable to aspeed,ast2500-vuart.
+      Phandle to aspeed,ast2500-scu or aspeed,ast2600-scu compatible syscon
+      alongside register offset and bit number to identify how the SIRQ
+      polarity should be configured. One possible data source is the LPC/eSPI
+      mode bit. Only applicable to aspeed,ast2500-vuart and
+      aspeed,ast2600-vuart.
     deprecated: true
 
   aspeed,lpc-io-reg:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     maxItems: 1
     description: |
-      The VUART LPC address.  Only applicable to aspeed,ast2500-vuart.
+      The VUART LPC address. Only applicable to aspeed,ast2500-vuart and
+      aspeed,ast2600-vuart.
 
   aspeed,lpc-interrupts:
     $ref: /schemas/types.yaml#/definitions/uint32-array
@@ -305,8 +313,8 @@ properties:
     maxItems: 2
     description: |
       A 2-cell property describing the VUART SIRQ number and SIRQ
-      polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH).  Only
-      applicable to aspeed,ast2500-vuart.
+      polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
+      applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
 
 required:
   - reg
Signature · 1 line
2.54.0
#2 lore raw

Re: [PATCH v4 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 317

Quoted 4 lines
Documentation/devicetree/bindings/serial/8250.yaml +2 -2
-      polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH).  Only
-      applicable to aspeed,ast2500-vuart.
+      polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
+      applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.

nitpick, if you need to respin. Don't change to two spaces to one.

Whitespace changes distract from real changes. So it is normal to put them in a patch of their own. In this case, i don't think it needs to change at all. Two spaces after a . is a common style.

Andrew

#3 lore raw

Re: [PATCH v4 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600

In reply to Grégoire Layet
Quoted 2 lines · Grégoire Layet

The ast2600 was using the ast2500 vuart compatible string. Make it possible to have ast2600-specific properties.

Then add these properties here as well. Adding a new device is one
commit: its compatible and its properties.

Quoted 33 lines
---
 .../devicetree/bindings/serial/8250.yaml      | 24 ++++++++++++-------
 1 file changed, 16 insertions(+), 8 deletions(-)
Documentation/devicetree/bindings/serial/8250.yaml +7 -1
index bb7b9c87a807..8f22121381fc 100644
@@ -23,7 +23,10 @@ allOf:
     then:
       properties:
         compatible:
-          const: aspeed,ast2500-vuart
+          contains:
+            enum:
+              - aspeed,ast2500-vuart
+              - aspeed,ast2600-vuart
   - if:
       properties:
         compatible:
@@ -106,6 +109,9 @@ properties:
       - const: ns16850
       - const: aspeed,ast2400-vuart
       - const: aspeed,ast2500-vuart
+      - items:
+          - const: aspeed,ast2600-vuart
+          - const: aspeed,ast2500-vuart
       - const: intel,xscale-uart
       - const: mrvl,pxa-uart
       - const: nuvoton,wpcm450-uart

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 296

Quoted 8 lines
Documentation/devicetree/bindings/serial/8250.yaml +1 -4
@@ -287,17 +293,19 @@ properties:
   aspeed,sirq-polarity-sense:
     $ref: /schemas/types.yaml#/definitions/phandle-array
     description: |
-      Phandle to aspeed,ast2500-scu compatible syscon alongside register
-      offset and bit number to identify how the SIRQ polarity should be
-      configured. One possible data source is the LPC/eSPI mode bit. Only
-      applicable to aspeed,ast2500-vuart.
+      Phandle to aspeed,ast2500-scu or aspeed,ast2600-scu compatible syscon

This is a deprecated property, so it cannot apply to a new device - aspeed,ast2600-vuart. You cannot use deprecated code for new bindings or device support.

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 301

Quoted 5 lines
Documentation/devicetree/bindings/serial/8250.yaml +4 -0
+      alongside register offset and bit number to identify how the SIRQ
+      polarity should be configured. One possible data source is the LPC/eSPI
+      mode bit. Only applicable to aspeed,ast2500-vuart and
+      aspeed,ast2600-vuart.
     deprecated: true

Best regards,
Krzysztof

#4 lore raw

Re: [PATCH v4 1/7] dt-bindings: serial: 8250: aspeed: add compatible string for ast2600

Hi Krzysztof,

Quoted 7 lines · Krzysztof Kozlowski
Quoted 2 lines · Grégoire Layet

The ast2600 was using the ast2500 vuart compatible string. Make it possible to have ast2600-specific properties.

Then add these properties here as well. Adding a new device is one
commit: its compatible and its properties.

I thought it was necessary to split the two. I will squash the two dt-bindings commits for the next revision.

Quoted 9 lines

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 296

Quoted 8 lines

aspeed,sirq-polarity-sense:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: |

Documentation/devicetree/bindings/serial/8250.yaml +1 -4
-      Phandle to aspeed,ast2500-scu compatible syscon alongside register
-      offset and bit number to identify how the SIRQ polarity should be
-      configured. One possible data source is the LPC/eSPI mode bit. Only
-      applicable to aspeed,ast2500-vuart.
+      Phandle to aspeed,ast2500-scu or aspeed,ast2600-scu compatible syscon
Quoted 3 lines

This is a deprecated property, so it cannot apply to a new device - aspeed,ast2600-vuart. You cannot use deprecated code for new bindings or device support.

True, I'll remove it.

Regards,
Grégoire

#5 lore raw

PATCH v4 2/7 dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop

In reply to Grégoire Layet

The ASPEED AST2600 has 2 Virtual UARTs accessible over PCI. The ASPEED AST2600 can be used as a PCI device.
2 Virtual UART can be exposed to the host via this PCI device. These are 8250-compatible register sets and can be used to have UART communication between the PCI BMC and the host.

This boolean can be set to specify if a VUART is used over PCI. A VUART over PCI needs a syscon phandle. The syscon gives a regmap to the SCU, which is used to set the enable bits of the PCI device.
On the aspeed's chips, the clocks phandle already points at the SCU node. But deriving the regmap from the clock provider would misuse the clocks binding. An explicit syscon phandle states the dependency directly.

---
 .../devicetree/bindings/serial/8250.yaml      | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)
Documentation/devicetree/bindings/serial/8250.yaml +22 -0
index 8f22121381fc..2ea8981bba80 100644
@@ -27,6 +27,16 @@ allOf:
             enum:
               - aspeed,ast2500-vuart
               - aspeed,ast2600-vuart
+  - if:
+      required:
+        - aspeed,vuart-over-pci
+    then:
+      required:
+        - syscon
+      properties:
+        compatible:
+          contains:
+            const: aspeed,ast2600-vuart
   - if:
       properties:
         compatible:
@@ -223,6 +233,12 @@ properties:
           - const: uartclk
           - const: reg
 
+  syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the SCU syscon, used to enable the VUART over the BMC PCI
+      device. Only applicable to aspeed,ast2600-vuart.
+
   dmas:
     minItems: 1
     maxItems: 4
@@ -316,6 +332,12 @@ properties:
       polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
       applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
 
+  aspeed,vuart-over-pci:
+    type: boolean
+    description:
+      Enable the VUART over the BMC PCI device. Only applicable to
+      aspeed,ast2600-vuart.
+
 required:
   - reg
   - interrupts
Signature · 1 line
2.54.0
#6 lore raw

Re: [PATCH v4 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] Missing schema constraint for `syscon` property allows it on all generic 8250 devices. --

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Missing schema constraint for syscon property allows it on all generic 8250 devices. --

--- Patch [2]: [PATCH v4 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop --- commit 4861ff4b770f95ffb3bbce902547b1d91b91628c
Author: Grégoire Layet <[email protected]>

dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop

This commit adds a boolean property to specify if a Virtual UART is used over PCI on the ASPEED AST2600. It also adds a syscon phandle requirement when this property is present.

Quoted 18 lines
Documentation/devicetree/bindings/serial/8250.yaml +10 -0
index 8f22121381fc4..2ea8981bba80f 100644
@@ -27,6 +27,16 @@ allOf:
             enum:
               - aspeed,ast2500-vuart
               - aspeed,ast2600-vuart
+  - if:
+      required:
+        - aspeed,vuart-over-pci
+    then:
+      required:
+        - syscon
+      properties:
+        compatible:
+          contains:
+            const: aspeed,ast2600-vuart

[ ... ]

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 240

Quoted 9 lines
Documentation/devicetree/bindings/serial/8250.yaml +5 -0
@@ -223,6 +233,12 @@ properties:
           - const: uartclk
           - const: reg
 
+  syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the SCU syscon, used to enable the VUART over the BMC PCI
+      device. Only applicable to aspeed,ast2600-vuart.

[Severity: Medium]
Will this schema allow the syscon property on all generic 8250 devices?

Because syscon is defined in the top-level properties block, and the newly added if block above only evaluates when aspeed,vuart-over-pci is present in the node, it seems there is no constraint restricting the use of syscon on other unrelated 8250 nodes (e.g., ns16550a). Device trees could specify a syscon property on non-AST2600 UARTs and silently pass schema validation, despite the documentation stating it is only applicable to aspeed,ast2600-vuart.

Should there be an additional conditional block restricting syscon to aspeed,ast2600-vuart as well?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#7 lore raw

Re: [PATCH v4 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop

In reply to Grégoire Layet
Quoted 26 lines · Grégoire Layet

The ASPEED AST2600 has 2 Virtual UARTs accessible over PCI. The ASPEED AST2600 can be used as a PCI device.
2 Virtual UART can be exposed to the host via this PCI device. These are 8250-compatible register sets and can be used to have UART communication between the PCI BMC and the host.

This boolean can be set to specify if a VUART is used over PCI. A VUART over PCI needs a syscon phandle. The syscon gives a regmap to the SCU, which is used to set the enable bits of the PCI device.
On the aspeed's chips, the clocks phandle already points at the SCU node. But deriving the regmap from the clock provider would misuse the clocks binding. An explicit syscon phandle states the dependency directly.

---
 .../devicetree/bindings/serial/8250.yaml      | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)
Documentation/devicetree/bindings/serial/8250.yaml +0 -0
index 8f22121381fc..2ea8981bba80 100644
@@ -27,6 +27,16 @@ allOf:
             enum:
               - aspeed,ast2500-vuart
               - aspeed,ast2600-vuart

Documentation/devicetree/bindings/serial/8250.yaml allOf: · line 39

Quoted 10 lines
Documentation/devicetree/bindings/serial/8250.yaml +10 -0
+  - if:
+      required:
+        - aspeed,vuart-over-pci
+    then:
+      required:
+        - syscon
+      properties:
+        compatible:
+          contains:
+            const: aspeed,ast2600-vuart

else:
...
disallow new properties (see example-schema)

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 236

Quoted 8 lines
Documentation/devicetree/bindings/serial/8250.yaml +1 -0
   - if:
       properties:
         compatible:
@@ -223,6 +233,12 @@ properties:
           - const: uartclk
           - const: reg
 
+  syscon:

That's explicitly forbidden by writing bindings (and mentioned as the antipattern in my older talks about DT).

Quoted 24 lines
Documentation/devicetree/bindings/serial/8250.yaml +11 -0
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the SCU syscon, used to enable the VUART over the BMC PCI
+      device. Only applicable to aspeed,ast2600-vuart.
+
   dmas:
     minItems: 1
     maxItems: 4
@@ -316,6 +332,12 @@ properties:
       polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
       applicable to aspeed,ast2500-vuart and aspeed,ast2600-vuart.
 
+  aspeed,vuart-over-pci:
+    type: boolean
+    description:
+      Enable the VUART over the BMC PCI device. Only applicable to
+      aspeed,ast2600-vuart.
+
 required:
   - reg
   - interrupts
Signature · 1 line
2.54.0
#8 lore raw

Re: [PATCH v4 2/7] dt-bindings: serial: 8250: aspeed: add aspeed,vuart-over-pci bool prop

Hi Krzysztof.

Quoted 11 lines · Krzysztof Kozlowski
Quoted 11 lines

...

Documentation/devicetree/bindings/serial/8250.yaml +6 -0
@@ -27,6 +27,16 @@ allOf:
             enum:
               - aspeed,ast2500-vuart
               - aspeed,ast2600-vuart
+  - if:
+      required:
+        - aspeed,vuart-over-pci
+    then:
+      required:
+        - syscon
Quoted 8 lines

Documentation/devicetree/bindings/serial/8250.yaml allOf: · line 39

Quoted 4 lines
Documentation/devicetree/bindings/serial/8250.yaml +4 -0
+      properties:
+        compatible:
+          contains:
+            const: aspeed,ast2600-vuart

else:
...
disallow new properties (see example-schema)

Yes it was missing. Acknowledged.

Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/serial/8250.yaml +0 -0
   - if:
       properties:
         compatible:
@@ -223,6 +233,12 @@ properties:
           - const: uartclk
           - const: reg
 
Quoted 4 lines

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 236

Quoted 1 line
Documentation/devicetree/bindings/serial/8250.yaml +1 -0
+  syscon:

That's explicitly forbidden by writing bindings (and mentioned as the antipattern in my older talks about DT).

Missed that.
Should it be named to 'aspeed,scu-syscon' as the aspeed SCU is used for all the peripherals.
Or should it be named to 'aspeed,pci-syscon' to specify its purpose in this context.

From what I have gathered, current convention would use the specific name 'aspeed,pci-syscon'.
Would like some feedback on this!

Quoted 6 lines

Documentation/devicetree/bindings/serial/8250.yaml properties: · line 241

Quoted 6 lines
Documentation/devicetree/bindings/serial/8250.yaml +5 -0
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the SCU syscon, used to enable the VUART over the BMC PCI
+      device. Only applicable to aspeed,ast2600-vuart.
+
...

Thanks

Regards,
Grégoire

#9 lore raw

PATCH v4 3/7 serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string

In reply to Grégoire Layet

Make the driver compatible with the ast2600-vuart. Enable specific configuration for the AST2600.

---
 drivers/tty/serial/8250/8250_aspeed_vuart.c | 1 +
 1 file changed, 1 insertion(+)
drivers/tty/serial/8250/8250_aspeed_vuart.c +1 -0
index 26fc0464f1cc..6afa2f4057e1 100644
@@ -560,6 +560,7 @@ static void aspeed_vuart_remove(struct platform_device *pdev)
 static const struct of_device_id aspeed_vuart_table[] = {
 	{ .compatible = "aspeed,ast2400-vuart" },
 	{ .compatible = "aspeed,ast2500-vuart" },
+	{ .compatible = "aspeed,ast2600-vuart" },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, aspeed_vuart_table);
Signature · 1 line
2.54.0
#10 lore raw

Re: [PATCH v4 3/7] serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Error paths in aspeed_vuart_probe() after serial port registration fail to unregister the port, leading to a Use-After-Free vulnerability.
- [High] Incorrect teardown ordering in aspeed_vuart_remove() allows the unthrottle timer to be re-armed after it is deleted, leading to a Use-After-Free vulnerability. --

--- Patch [3]: [PATCH v4 3/7] serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string --- commit be545f82b6eac2794c78d897d8e0ac9945c563d1
Author: Grégoire Layet <[email protected]>

serial: 8250_aspeed_vuart: add aspeed,ast2600-vuart compatible string

Make the driver compatible with the ast2600-vuart. Enable specific configuration for the AST2600.

drivers/tty/serial/8250/8250_aspeed_vuart.c static void aspeed_vuart_remove(struct platform_device *pdev) · line 565

Quoted 11 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +1 -0
index 26fc0464f1cc2..6afa2f4057e1b 100644
@@ -560,6 +560,7 @@ static void aspeed_vuart_remove(struct platform_device *pdev)
 static const struct of_device_id aspeed_vuart_table[] = {
 	{ .compatible = "aspeed,ast2400-vuart" },
 	{ .compatible = "aspeed,ast2500-vuart" },
+	{ .compatible = "aspeed,ast2600-vuart" },
 	{ },
 };

[Severity: High]
This isn't a bug introduced by this patch, but the error paths in aspeed_vuart_probe() after serial port registration fail to unregister the port.

If an initialization step fails after serial8250_register_8250_port() (e.g. if aspeed_vuart_set_lpc_address() returns -EINVAL), the code jumps here:

drivers/tty/serial/8250/8250_aspeed_vuart.c:aspeed_vuart_probe() {
    ...
err_sysfs_remove:
	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
	return rc;
}

This error path omits serial8250_unregister_port(vuart->line) and timer_delete_sync(&vuart->unthrottle_timer), leaking the registered port.

Since the vuart struct is then freed by devres, if a user opens the leaked serial port, aspeed_vuart_startup() will dereference the freed vuart struct.

Should the error path unregister the port and delete the timer?

[Severity: High]
This isn't a bug introduced by this patch, but there is an incorrect teardown ordering in aspeed_vuart_remove() that allows the unthrottle timer to be re-armed after it is deleted.

drivers/tty/serial/8250/8250_aspeed_vuart.c:aspeed_vuart_remove() {
	struct aspeed_vuart *vuart = platform_get_drvdata(pdev);

	timer_delete_sync(&vuart->unthrottle_timer);
	aspeed_vuart_set_enabled(vuart, false);
	serial8250_unregister_port(vuart->line);
	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
}

Because timer_delete_sync() is invoked before serial8250_unregister_port(), the UART and its IRQ are still fully active. An incoming interrupt can trigger aspeed_vuart_handle_irq(), and if the tty buffer is full, re-arm the timer via mod_timer().

When the driver removal completes, the vuart struct is freed by devres. When the re-armed timer fires, aspeed_vuart_unthrottle_exp() will dereference the freed vuart struct.

Could the timer be deleted after unregistering the serial port to prevent it from being re-armed?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
#11 lore raw

PATCH v4 4/7 serial: 8250_aspeed_vuart: add VUART over PCI

In reply to Grégoire Layet

Enable the VUART over PCI for the AST2600. Activate it only if the 'aspeed,vuart-over-pci' property flag is set on an 'ast2600-vuart' compatible node.

The AST2600 has 2 VUART that are usable over PCI. These are already defined as the VUART3 and VUART4 in the 'aspeed-g6.dtsi'.

Sets the BMC PCI device enable bits, sets the PCI class code to unassgined/device specific, and configures MSI interrupts.

There is no disable function. Removing this driver should not disable the BMC PCI device, as other drivers could use it.
However, if all the drivers using it are removed, the
BMC PCI device will still be activated, which is not ideal. But in reality, this is not a use case for a BMC, the drivers will never be removed.

This is useful on PCIe BMC expansion cards that use the AST2600, such as the ASUS Kommando IPMI Expansion Card.

Register initialisation taken from ASPEED 6.18 Kernel SDK. Add return code checks to each register write. Simplify the code and add macros.

The ASPEED_SCUC24 regmap update is missing a macro for 'BIT(14)'. I was unable to determine the purpose of this bit. In the AST2600 A3 datasheet it is marked as 'reserved'. It is only used on the other revision. As I only have the AST2600A3, I was unable to try this code path. This BIT14 was set in the ASPEED SDK so I kept it.
I can remove it and the untested path if necessary.

---
 drivers/tty/serial/8250/8250_aspeed_vuart.c | 86 +++++++++++++++++++++
 1 file changed, 86 insertions(+)
drivers/tty/serial/8250/8250_aspeed_vuart.c +86 -0
index 6afa2f4057e1..4d09c04cb972 100644
@@ -32,6 +32,26 @@
 #define ASPEED_VUART_DEFAULT_SIRQ	4
 #define ASPEED_VUART_DEFAULT_SIRQ_POLARITY	IRQ_TYPE_LEVEL_LOW
 
+#define ASPEED_SCU_SILICON_REVISION_ID			0x04
+#define AST2600A3_REVISION_ID				0x05030303
+
+#define ASPEED_SCUC24			0xC24
+#define  ASPEED_SCUC24_MSI_ROUTING_MASK			GENMASK(11, 10)
+#define  ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1		(0x2 << 10)
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN		BIT(18)
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN			BIT(17)
+
+#define ASPEED_SCU_PCIE_CONF_CTRL	0xC20
+#define  SCU_PCIE_CONF_BMC_DEV_EN					BIT(8)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_MMIO				BIT(9)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_MSI				BIT(11)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_IRQ				BIT(13)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER	BIT(14)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_E2L				BIT(15)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE		BIT(21)
+
+#define ASPEED_SCU_BMC_DEV_CLASS	0xC68
+
 struct aspeed_vuart {
 	struct device		*dev;
 	int			line;
@@ -412,6 +432,63 @@ static int aspeed_vuart_map_irq_polarity(u32 dt)
 	}
 }
 
+static int aspeed_ast2600_vuart_over_pci_set_enabled(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	u32 silicon_revision_id;
+	struct regmap *scu;
+	int rc;
+
+	u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ |
+				SCU_PCIE_CONF_BMC_DEV_EN_MMIO |
+				SCU_PCIE_CONF_BMC_DEV_EN_MSI |
+				SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER |
+				SCU_PCIE_CONF_BMC_DEV_EN_E2L |
+				SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE |
+				SCU_PCIE_CONF_BMC_DEV_EN;
+
+	scu = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
+	if (IS_ERR(scu)) {
+		dev_err(&pdev->dev, "failed to find SCU regmap\n");
+		return PTR_ERR(scu);
+	}
+
+	/* update class code to be an Unassigned/device specific class device */
+	if (regmap_write(scu, ASPEED_SCU_BMC_DEV_CLASS, 0xff000000)) {
+		dev_err(dev, "could not set PCI class code\n");
+		return -EIO;
+	}
+
+	if (regmap_update_bits(scu, ASPEED_SCU_PCIE_CONF_CTRL,
+			       pcie_config_ctl, pcie_config_ctl)) {
+		dev_err(dev, "could not set PCIe configuration\n");
+		return -EIO;
+	}
+
+	if (regmap_read(scu, ASPEED_SCU_SILICON_REVISION_ID, &silicon_revision_id)) {
+		dev_err(dev, "could not read silicon revision\n");
+		return -EIO;
+	}
+
+	if (silicon_revision_id == AST2600A3_REVISION_ID)
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	else
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					/**
+					 * The bit 14 is reserved in the Datasheet.
+					 */
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	if (rc) {
+		dev_err(dev, "could not set PCI device 1 MSI interrupt routing\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int aspeed_vuart_probe(struct platform_device *pdev)
 {
 	struct of_phandle_args sirq_polarity_sense_args;
@@ -540,6 +617,15 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
 	aspeed_vuart_set_host_tx_discard(vuart, true);
 	platform_set_drvdata(pdev, vuart);
 
+	if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-vuart") &&
+	    of_property_read_bool(dev->of_node, "aspeed,vuart-over-pci")) {
+		rc = aspeed_ast2600_vuart_over_pci_set_enabled(pdev);
+		if (rc < 0) {
+			dev_err_probe(dev, rc, "could not enable VUART over PCI\n");
+			goto err_sysfs_remove;
+		}
+	}
+
 	return 0;
 
 err_sysfs_remove:
Signature · 1 line
2.54.0
#12 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Probe error paths fail to unregister the 8250 serial port and cancel the unthrottle timer, causing a resource leak and potential use-after-free.
- [High] Sysfs attributes are exposed before the driver data is set, creating a race window that leads to a NULL pointer dereference. --

--- Patch [4]: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI --- commit d4ec19577207abb14c5ca6354d48ef6da9508b14
Author: Grégoire Layet <[email protected]>

serial: 8250_aspeed_vuart: add VUART over PCI

Enable the VUART over PCI for the AST2600. Activate it only if the 'aspeed,vuart-over-pci' property flag is set on an 'ast2600-vuart' compatible node.

Quoted 4 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +0 -0
index 6afa2f4057e1b..4d09c04cb9727 100644

[ ... ]

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 618

Quoted 3 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +0 -0
@@ -540,6 +617,15 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
 	aspeed_vuart_set_host_tx_discard(vuart, true);
 	platform_set_drvdata(pdev, vuart);

[Severity: High]
This is a pre-existing issue, but setting the driver data this late creates a race condition.

The sysfs attribute group is created earlier in aspeed_vuart_probe():

    rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);

If userspace accesses these sysfs files (e.g., triggering sirq_show()) before platform_set_drvdata() is called here, dev_get_drvdata() returns NULL, which then leads to a NULL pointer dereference.

Could the sysfs creation be deferred until after the driver data is set?

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 625

Quoted 7 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +6 -0
+	if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-vuart") &&
+	    of_property_read_bool(dev->of_node, "aspeed,vuart-over-pci")) {
+		rc = aspeed_ast2600_vuart_over_pci_set_enabled(pdev);
+		if (rc < 0) {
+			dev_err_probe(dev, rc, "could not enable VUART over PCI\n");
+			goto err_sysfs_remove;

[Severity: High]
This is a pre-existing issue, but this error path fails to unregister the 8250 serial port and cancel the unthrottle timer.

If aspeed_ast2600_vuart_over_pci_set_enabled() fails, we jump to err_sysfs_remove:

err_sysfs_remove:

	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
	return rc;
}

This cleans up the sysfs group but leaves the serial port registered.

Since the vuart structure is allocated with devm_kzalloc, it will be freed automatically by devres when the probe fails. This leaves a dangling pointer in the active 8250 serial port's private data, which can result in a use-after-free if the TTY device is accessed.

Should this error path also call serial8250_unregister_port() and timer_delete_sync() before returning?

Quoted 6 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +3 -0
+		}
+	}
+
 	return 0;
 
 err_sysfs_remove:
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
#13 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

In reply to Grégoire Layet

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 483

Quoted 11 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +11 -0
+	if (silicon_revision_id == AST2600A3_REVISION_ID)
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	else
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					/**
+					 * The bit 14 is reserved in the Datasheet.
+					 */
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);

checkpatch should be warning about these long lines. Traditionally, the limit is 80 character lines, but recently 100 has been accepted by some subsystems. The exception is when wrapping the lines will make them less readable, but i don't think that applies here.

Andrew

maintainer
#14 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

Quoted 8 lines · Andrew Lunn
Quoted 8 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +8 -0
+	if (silicon_revision_id == AST2600A3_REVISION_ID)
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	else
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					/**
+					 * The bit 14 is reserved in the Datasheet.
Quoted 8 lines

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 483

Quoted 3 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +3 -0
+					 */
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);

checkpatch should be warning about these long lines. Traditionally, the limit is 80 character lines, but recently 100 has been accepted by some subsystems. The exception is when wrapping the lines will make them less readable, but i don't think that applies here.

FWIW 100 is fine by me. 80 is too ancient limit.

Signature · 2 lines
js
suse labs
#15 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

Quoted 14 lines · Jiri Slaby
Quoted 12 lines · Andrew Lunn
Quoted 11 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +11 -0
+    if (silicon_revision_id == AST2600A3_REVISION_ID)
+            rc = regmap_update_bits(scu, ASPEED_SCUC24,
+                                    ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+                                    ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+    else
+            rc = regmap_update_bits(scu, ASPEED_SCUC24,
+                                    /**
+                                     * The bit 14 is reserved in the Datasheet.
+                                     */
+                                    ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+                                    ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
Quoted 6 lines
Quoted 4 lines

checkpatch should be warning about these long lines. Traditionally, the limit is 80 character lines, but recently 100 has been accepted by some subsystems. The exception is when wrapping the lines will make them less readable, but i don't think that applies here.

FWIW 100 is fine by me. 80 is too ancient limit.

Modified to fit 100 characters-per-line limit.
No checkpatch warning.

Regards,
Grégoire

maintainer
#16 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

In reply to Grégoire Layet

On 08. 07. 26, 17:35, Grégoire Layet wrote:
...

drivers/tty/serial/8250/8250_aspeed_vuart.c line 40

Quoted 12 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +6 -0
@@ -32,6 +32,26 @@
  #define ASPEED_VUART_DEFAULT_SIRQ	4
  #define ASPEED_VUART_DEFAULT_SIRQ_POLARITY	IRQ_TYPE_LEVEL_LOW
 
+#define ASPEED_SCU_SILICON_REVISION_ID			0x04
+#define AST2600A3_REVISION_ID				0x05030303
+
+#define ASPEED_SCUC24			0xC24
+#define  ASPEED_SCUC24_MSI_ROUTING_MASK			GENMASK(11, 10)
+#define  ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1		(0x2 << 10)

So is this
FIELD_PREP(ASPEED_SCUC24_MSI_ROUTING_MASK, 2)
?

drivers/tty/serial/8250/8250_aspeed_vuart.c line 42

Quoted 2 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +2 -0
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN		BIT(18)
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN			BIT(17)

Perhaps switch the two (to be in asc order)? And define 14 as _RESERVED as well?

drivers/tty/serial/8250/8250_aspeed_vuart.c line 44

Quoted 1 line
drivers/tty/serial/8250/8250_aspeed_vuart.c +1 -0
+#define ASPEED_SCU_PCIE_CONF_CTRL	0xC20

Hmm, should these go before 0xC24?

Quoted 19 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +12 -0
+#define  SCU_PCIE_CONF_BMC_DEV_EN					BIT(8)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_MMIO				BIT(9)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_MSI				BIT(11)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_IRQ				BIT(13)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER	BIT(14)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_E2L				BIT(15)
+#define  SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE		BIT(21)
+
+#define ASPEED_SCU_BMC_DEV_CLASS	0xC68
+
  struct aspeed_vuart {
  	struct device		*dev;
  	int			line;
@@ -412,6 +432,63 @@ static int aspeed_vuart_map_irq_polarity(u32 dt)
  	}
  }
 
+static int aspeed_ast2600_vuart_over_pci_set_enabled(struct platform_device *pdev)
+{

...

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 481

Quoted 9 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +9 -0
+	if (silicon_revision_id == AST2600A3_REVISION_ID)
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	else
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					/**
+					 * The bit 14 is reserved in the Datasheet.
+					 */

If you defined reserved as suggested above, no need for the comment.

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 491

Quoted 10 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +10 -0
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN | BIT(14) | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	if (rc) {
+		dev_err(dev, "could not set PCI device 1 MSI interrupt routing\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+

thanks,

Signature · 2 lines
js
suse labs
#17 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

Hi Jiri,

Quoted 9 lines · Jiri Slaby

On 08. 07. 26, 17:35, Grégoire Layet wrote:
...

Quoted 6 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +0 -0
@@ -32,6 +32,26 @@
  #define ASPEED_VUART_DEFAULT_SIRQ   4
  #define ASPEED_VUART_DEFAULT_SIRQ_POLARITY  IRQ_TYPE_LEVEL_LOW
 
Quoted 10 lines

drivers/tty/serial/8250/8250_aspeed_vuart.c line 40

Quoted 6 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +6 -0
+#define ASPEED_SCU_SILICON_REVISION_ID                       0x04
+#define AST2600A3_REVISION_ID                                0x05030303
+
+#define ASPEED_SCUC24                        0xC24
+#define  ASPEED_SCUC24_MSI_ROUTING_MASK                      GENMASK(11, 10)
+#define  ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1          (0x2 << 10)

So is this
FIELD_PREP(ASPEED_SCUC24_MSI_ROUTING_MASK, 2)
?

Yes, replaced

Quoted 6 lines

drivers/tty/serial/8250/8250_aspeed_vuart.c line 42

Quoted 3 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +2 -0
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN          BIT(18)
+#define  ASPEED_SCUC24_PCIDEV1_INTX_MSI_SCU560_EN                    BIT(17)

Perhaps switch the two (to be in asc order)? And define 14 as _RESERVED as well?

Acknowledged. I have also removed the comment afterwards.

Quoted 3 lines

drivers/tty/serial/8250/8250_aspeed_vuart.c line 44

Quoted 1 line
drivers/tty/serial/8250/8250_aspeed_vuart.c +1 -0
+#define ASPEED_SCU_PCIE_CONF_CTRL    0xC20

Hmm, should these go before 0xC24?

Yes

Thanks for the feedback, I have made the changes for the next revision.

Regards,
Grégoire

#18 lore raw

Re: [PATCH v4 4/7] serial: 8250_aspeed_vuart: add VUART over PCI

In reply to Grégoire Layet
Quoted 23 lines

Enable the VUART over PCI for the AST2600. Activate it only if the 'aspeed,vuart-over-pci' property flag is set on an 'ast2600-vuart' compatible node.

The AST2600 has 2 VUART that are usable over PCI. These are already defined as the VUART3 and VUART4 in the 'aspeed-g6.dtsi'.

Sets the BMC PCI device enable bits, sets the PCI class code to unassgined/device specific, and configures MSI interrupts.

There is no disable function. Removing this driver should not disable the BMC PCI device, as other drivers could use it.
However, if all the drivers using it are removed, the
BMC PCI device will still be activated, which is not ideal. But in reality, this is not a use case for a BMC, the drivers will never be removed.

This is useful on PCIe BMC expansion cards that use the AST2600, such as the ASUS Kommando IPMI Expansion Card.

Register initialisation taken from ASPEED 6.18 Kernel SDK. Add return code checks to each register write. Simplify the code and add macros.

Quoted 6 lines

The ASPEED_SCUC24 regmap update is missing a macro for 'BIT(14)'. I was unable to determine the purpose of this bit. In the AST2600 A3 datasheet it is marked as 'reserved'. It is only used on the other revision. As I only have the AST2600A3, I was unable to try this code path. This BIT14 was set in the ASPEED SDK so I kept it.
I can remove it and the untested path if necessary.

There's not even a reference in the datasheet changelog, so I suspect that it has always been reserved.
I'd be in favour of removing it.

drivers/tty/serial/8250/8250_aspeed_vuart.c

Quoted 9 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +0 -0
index 6afa2f4057e1..4d09c04cb972 100644

*snip*

Quoted 8 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +8 -0
+static int aspeed_ast2600_vuart_over_pci_set_enabled(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	u32 silicon_revision_id;
+	struct regmap *scu;
+	int rc;
+
+	u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ |

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 452

Quoted 10 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +10 -0
+				SCU_PCIE_CONF_BMC_DEV_EN_MMIO |
+				SCU_PCIE_CONF_BMC_DEV_EN_MSI |
+				SCU_PCIE_CONF_BMC_DEV_EN_PCIE_BUS_MASTER |
+				SCU_PCIE_CONF_BMC_DEV_EN_E2L |
+				SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE |
+				SCU_PCIE_CONF_BMC_DEV_EN;
+
+	scu = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
+	if (IS_ERR(scu)) {
+		dev_err(&pdev->dev, "failed to find SCU regmap\n");

dev_err(dev, ...) instead of &pdev->dev (defined above).

Quoted 19 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +19 -0
+		return PTR_ERR(scu);
+	}
+
+	/* update class code to be an Unassigned/device specific class device */
+	if (regmap_write(scu, ASPEED_SCU_BMC_DEV_CLASS, 0xff000000)) {
+		dev_err(dev, "could not set PCI class code\n");
+		return -EIO;
+	}
+
+	if (regmap_update_bits(scu, ASPEED_SCU_PCIE_CONF_CTRL,
+			       pcie_config_ctl, pcie_config_ctl)) {
+		dev_err(dev, "could not set PCIe configuration\n");
+		return -EIO;
+	}
+
+	if (regmap_read(scu, ASPEED_SCU_SILICON_REVISION_ID, &silicon_revision_id)) {
+		dev_err(dev, "could not read silicon revision\n");
+		return -EIO;
+	}

drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_map_irq_polarity(u32 dt) · line 481

Quoted 10 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +10 -0
+
+	if (silicon_revision_id == AST2600A3_REVISION_ID)
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_MASK,
+					ASPEED_SCUC24_PCIDEV1_INTX_MSI_HOST2BMC_EN | ASPEED_SCUC24_MSI_ROUTING_PCIE2LPC_PCIDEV1);
+	else
+		rc = regmap_update_bits(scu, ASPEED_SCUC24,
+					/**
+					 * The bit 14 is reserved in the Datasheet.
+					 */

Even in the oldest datasheet that I've got (which was for A2 apparently) it is marked as reserved.

Maybe some ASPEED folks can enlighten us what Bits 14 till 16 were used for on A0-A2, and if they are relevant for PCIe INTx/MSI routing on the older silicons.

Tan

Signature · 1 line
Tan Siewert <[email protected]>
#19 lore raw

PATCH v4 5/7 soc: aspeed: add host-side PCIe BMC device driver

In reply to Grégoire Layet

Add support for VUART over PCIe between BMC and host. Add the host side driver.
Support only the AST2600.

Taken from ASPEED 6.18 Kernel SDK and trimmed down.

The host can't detect the VUART addresses, so force them to 0x3f8 and 0x2f8, as in the initial ASPEED driver.

Change the MSI vector index of VUART2 from 15 to 17. The index 15 used in the initial driver was not working.

Data path in both direction is tested on both VUART.

This module is added in soc/aspeed as it's very soc specific. This is not added as a PCI 8250 UART device as this host module can be expanded upon for IPMI over KCS. It can also be used in the future for custom BMC<->host communication with shared memory and doorbell.

This host module should be the entry point for setting up all features related to an AST2600 present on the PCI bus.

---
 drivers/soc/aspeed/Kconfig               |  15 ++
 drivers/soc/aspeed/Makefile              |   1 +
 drivers/soc/aspeed/aspeed-host-bmc-dev.c | 174 +++++++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c
drivers/soc/aspeed/Kconfig +15 -0
index f579ee0b5afa..147a9033bdc4 100644
@@ -55,3 +55,18 @@ config ASPEED_SOCINFO
 endmenu
 
 endif
+
+menu "ASPEED host-side drivers"
+	depends on PCI
+
+config ASPEED_HOST_BMC_DEV
+	tristate "ASPEED host-side BMC PCIe device"
+	depends on SERIAL_8250
+	help
+	  Host-side driver for the ASPEED AST2600 BMC PCIe device found on
+	  BMC expansion cards. Exposes two 8250-compatible VUART
+	  ports.
+
+	  If unsure, say N. Choose M to build aspeed-host-bmc-dev.
+
+endmenu
drivers/soc/aspeed/Makefile +1 -0
index b35d74592964..c515e163eab7 100644
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ASPEED_HOST_BMC_DEV)	+= aspeed-host-bmc-dev.o
 obj-$(CONFIG_ASPEED_LPC_CTRL)		+= aspeed-lpc-ctrl.o
 obj-$(CONFIG_ASPEED_LPC_SNOOP)		+= aspeed-lpc-snoop.o
 obj-$(CONFIG_ASPEED_UART_ROUTING)	+= aspeed-uart-routing.o
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +174 -0

174 lines not on this page · raw message

Signature · 1 line
2.54.0
#20 lore raw

Re: [PATCH v4 5/7] soc: aspeed: add host-side PCIe BMC device driver

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] The physical address of the PCI BAR is stored in an `unsigned long`, which silently truncates…

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] The physical address of the PCI BAR is stored in an unsigned long, which silently truncates addresses on 32-bit architectures with 64-bit physical addressing.
- [Medium] The driver requests legacy INTx interrupt fallback but enforces a minimum vector count of 32 and hardcodes MSI vector indices, making INTx support impossible.
- [Low] Missing newline character \n at the end of a pr_err message string.
- [Low] The probe error message references a non-existent function aspeed_pci_setup_irq_resource() instead of pci_alloc_irq_vectors().
- [Low] The driver computes a physical memory address for the UART mapped registers by adding a fixed offset to the base of PCI BAR 1, but fails to verify if BAR 1 exists or is large enough to contain this offset. --

--- Patch [5]: [PATCH v4 5/7] soc: aspeed: add host-side PCIe BMC device driver --- commit 466ab6d1aa3de4b6bd606a9368f52aa1b3fbe52e
Author: Grégoire Layet <[email protected]>
Subject: soc: aspeed: add host-side PCIe BMC device driver

This patch adds a host-side driver for the ASPEED AST2600 BMC PCIe device. It exposes two 8250-compatible VUART ports over PCIe between the BMC and the host.

Quoted 5 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +0 -0
new file mode 100644
index 0000000000000..e586d05055775

[ ... ]

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 25

Quoted 2 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +2 -0
+struct aspeed_pci_bmc_dev {
+	unsigned long message_bar_base;

[Severity: High]
Can this cause address truncation on 32-bit architectures with 64-bit physical addressing?

The physical address returned by pci_resource_start() is stored in an unsigned long, which is 32 bits on 32-bit platforms.

Should message_bar_base be typed as resource_size_t or phys_addr_t instead?

[ ... ]

Quoted 2 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +2 -0
+static int aspeed_pci_bmc_device_setup_vuart(struct pci_dev *pdev, int idx)
+{

[ ... ]

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 52

Quoted 3 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +3 -0
+	uart->port.iotype = UPIO_MEM32;
+	uart->port.iobase = 0;
+	uart->port.mapbase = pci_bmc_dev->message_bar_base + vuart_ioport;

[Severity: Low]
Is it safe to add the VUART offset to the base of BAR 1 without validation?

If BAR 1 is uninitialized or not large enough to contain vuart_ioport, this could result in an invalid physical memory address.

Should this code check pci_resource_len() before adding the offset?

[ ... ]

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 85

Quoted 9 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +9 -0
+static int aspeed_pci_host_setup(struct pci_dev *pdev)
+{
+	struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+	int rc = 0;
+
+	pci_bmc_dev->message_bar_base = pci_resource_start(pdev, 1);
+
+	if (pdev->revision == 0x27) {
+		pr_err("AST2700 detected but not supported");

[Severity: Low]
This isn't a bug, but there's a missing newline character at the end of this error message. Without the \n, subsequent printk messages might be accidentally concatenated onto the same line.

[ ... ]

Quoted 2 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +2 -0
+static int aspeed_pci_host_bmc_device_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{

[ ... ]

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 123

Quoted 4 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +4 -0
+	pci_set_master(pdev);
+	pci_set_drvdata(pdev, pci_bmc_dev);
+
+	rc = pci_alloc_irq_vectors(pdev, BMC_MULTI_MSI, BMC_MULTI_MSI, PCI_IRQ_INTX | PCI_IRQ_MSI);

[Severity: Medium]
Does this PCI_IRQ_INTX fallback function as intended?

The allocation requests a minimum of 32 vectors (BMC_MULTI_MSI), but INTx only supports a single vector, so the fallback will always fail.

Also, aspeed_pci_bmc_device_setup_vuart() hardcodes the vector indices:

	uart->port.irq = pci_irq_vector(pdev, vuart_msi_index[idx]);

Since indices 16 and 17 are invalid for INTx, will this driver completely fail to initialize on systems where MSI is disabled or unavailable?

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 125

Quoted 2 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +2 -0
+	if (rc < 0) {
+		dev_err(&pdev->dev, "aspeed_pci_setup_irq_resource() returned error %d\n", rc);

[Severity: Low]
Is the function name in this log message incorrect? It references aspeed_pci_setup_irq_resource() instead of pci_alloc_irq_vectors(), which might make debugging confusing.

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
maintainer
#21 lore raw

Re: [PATCH v4 5/7] soc: aspeed: add host-side PCIe BMC device driver

In reply to Grégoire Layet
Quoted 5 lines · Grégoire Layet

Add support for VUART over PCIe between BMC and host. Add the host side driver.
Support only the AST2600.

Taken from ASPEED 6.18 Kernel SDK and trimmed down.

...

Quoted 11 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +8 -0
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (C) ASPEED Technology Inc.
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 18

Quoted 10 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +10 -0
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#define BMC_MULTI_MSI	32
+#define PCI_BMC_DEVICE_ID 0x2402
+
+#define DRIVER_NAME "aspeed-host-bmc-dev"
+
+enum aspeed_platform_id {
+	ASPEED,

What is this good for?

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 22

Quoted 4 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +4 -0
+};
+
+static const int vuart_msi_index[2] = { 16, 17 };
+static const int vuart_port_addr[2] = {0x3f8, 0x2f8};

Sort of inconsistent spaces. Both arrays should be unsigned anyway. And for the latter, u16 should be enough.

Quoted 11 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +11 -0
+struct aspeed_pci_bmc_dev {
+	unsigned long message_bar_base;
+
+	struct uart_8250_port uart[2];
+	int uart_line[2];
+};
+
+static int aspeed_pci_bmc_device_setup_vuart(struct pci_dev *pdev, int idx)
+{
+	struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 44

Quoted 10 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +10 -0
+	struct uart_8250_port *uart = &pci_bmc_dev->uart[idx];
+	u16 vuart_ioport;
+	int ret;
+
+	/* Assign the line to non-exist device before everything is setup */
+	pci_bmc_dev->uart_line[idx] = -ENOENT;
+
+	vuart_ioport = vuart_port_addr[idx];
+	/* ASPEED BMC device shift addresses by 2 to the left */
+	vuart_ioport = vuart_ioport << 2;

Simply:
vuart_ioport <<= 2;
? Or join the two lines?

Quoted 22 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +22 -0
+	uart->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	uart->port.uartclk = 115200 * 16;
+	uart->port.irq = pci_irq_vector(pdev, vuart_msi_index[idx]);
+	uart->port.dev = dev;
+	uart->port.iotype = UPIO_MEM32;
+	uart->port.iobase = 0;
+	uart->port.mapbase = pci_bmc_dev->message_bar_base + vuart_ioport;
+	uart->port.membase = 0;
+	uart->port.type = PORT_16550A;
+	uart->port.flags |= (UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	uart->port.regshift = 2;
+
+	ret = serial8250_register_8250_port(&pci_bmc_dev->uart[idx]);
+	if (ret < 0) {
+		dev_err_probe(dev, ret, "Can't setup PCIe VUART%d\n", idx);
+		return ret;
+	}
+
+	pci_bmc_dev->uart_line[idx] = ret;
+
+	return 0;
+}

...

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 156

Quoted 3 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +3 -0
+static struct pci_device_id aspeed_host_bmc_dev_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ASPEED, PCI_BMC_DEVICE_ID),
+		.class = 0xFF0000, .class_mask = 0xFFFF00,

PCI_CLASS_OTHERS << 16

Quoted 8 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +8 -0
+		.driver_data = ASPEED },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, aspeed_host_bmc_dev_pci_ids);
+
+static struct pci_driver aspeed_host_bmc_dev_driver = {
+	.name		= DRIVER_NAME,

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 174

Quoted 10 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +10 -0
+	.id_table	= aspeed_host_bmc_dev_pci_ids,
+	.probe		= aspeed_pci_host_bmc_device_probe,
+	.remove		= aspeed_pci_host_bmc_device_remove,
+};
+
+module_driver(aspeed_host_bmc_dev_driver, pci_register_driver, pci_unregister_driver);
+
+MODULE_AUTHOR("Ryan Chen <[email protected]>");
+MODULE_DESCRIPTION("ASPEED Host BMC DEVICE Driver");
+MODULE_LICENSE("GPL");

thanks,

Signature · 2 lines
js
suse labs
#22 lore raw

Re: [PATCH v4 5/7] soc: aspeed: add host-side PCIe BMC device driver

Hi Jiri,

Quoted 6 lines

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 18

Quoted 4 lines

...

drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +3 -0
+
+enum aspeed_platform_id {
+     ASPEED,

What is this good for?

Unecessary, it's removed now.

Quoted 8 lines

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 22

Quoted 5 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +4 -0
+};
+
+static const int vuart_msi_index[2] = { 16, 17 };
+static const int vuart_port_addr[2] = {0x3f8, 0x2f8};

Sort of inconsistent spaces. Both arrays should be unsigned anyway. And for the latter, u16 should be enough.

True. Acknowledged.

Quoted 9 lines

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 44

Quoted 5 lines

...

drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +4 -0
+
+     vuart_ioport = vuart_port_addr[idx];
+     /* ASPEED BMC device shift addresses by 2 to the left */
+     vuart_ioport = vuart_ioport << 2;

Simply:
vuart_ioport <<= 2;
? Or join the two lines?

Joined the two lines.

Quoted 6 lines

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 156

Quoted 4 lines

...

drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +3 -0
+static struct pci_device_id aspeed_host_bmc_dev_pci_ids[] = {
+     { PCI_DEVICE(PCI_VENDOR_ID_ASPEED, PCI_BMC_DEVICE_ID),
+             .class = 0xFF0000, .class_mask = 0xFFFF00,

PCI_CLASS_OTHERS << 16

Acknowledged

Quoted 5 lines
Quoted 1 line

...

thanks,
--
js
suse labs

Thanks for the review. Applied everything for the next revision.

Regards,
Grégoire

#23 lore raw

Re: [PATCH v4 5/7] soc: aspeed: add host-side PCIe BMC device driver

In reply to Grégoire Layet
Quoted 14 lines

Add support for VUART over PCIe between BMC and host. Add the host side driver.
Support only the AST2600.

Taken from ASPEED 6.18 Kernel SDK and trimmed down.

The host can't detect the VUART addresses, so force them to 0x3f8 and 0x2f8, as in the initial ASPEED driver.

Change the MSI vector index of VUART2 from 15 to 17. The index 15 used in the initial driver was not working.

Quoted 6 lines

Data path in both direction is tested on both VUART.

This module is added in soc/aspeed as it's very soc specific. This is not added as a PCI 8250 UART device as this host module can be expanded upon for IPMI over KCS. It can also be used in the future for custom BMC<->host communication with shared memory and doorbell.

While I understand that this driver could be expanded with more features, it is still not fitting soc/aspeed as it is not for the ASPEED SoC, but for systems that communicate with an ASPEED SoC.

Maybe drivers/misc is more fitting for this?

Quoted 13 lines

This host module should be the entry point for setting up all features related to an AST2600 present on the PCI bus.

drivers/soc/aspeed/Kconfig +0 -0
index f579ee0b5afa..147a9033bdc4 100644

drivers/soc/aspeed/Kconfig config ASPEED_SOCINFO · line 63

Quoted 9 lines
drivers/soc/aspeed/Kconfig +6 -0
@@ -55,3 +55,18 @@ config ASPEED_SOCINFO
 endmenu
 
 endif
+
+menu "ASPEED host-side drivers"
+	depends on PCI
+
+config ASPEED_HOST_BMC_DEV
+	tristate "ASPEED host-side BMC PCIe device"

"device driver" would be more fitting instead of "host-side driver" I'd say.

drivers/soc/aspeed/Kconfig config ASPEED_SOCINFO · line 68

Quoted 5 lines
drivers/soc/aspeed/Kconfig +5 -0
+	depends on SERIAL_8250
+	help
+	  Host-side driver for the ASPEED AST2600 BMC PCIe device found on
+	  BMC expansion cards. Exposes two 8250-compatible VUART
+	  ports.

In the commit message you're stating that the device driver can be expanded for e.g. IPMI over KCS. Should the user be able to disable features selectively, or do they have to always have 8250 serial support active?

drivers/soc/aspeed/aspeed-host-bmc-dev.c

Quoted 19 lines
drivers/soc/aspeed/Kconfig +4 -0
+
+	  If unsure, say N. Choose M to build aspeed-host-bmc-dev.
+
+endmenu
drivers/soc/aspeed/Makefile +1 -0
index b35d74592964..c515e163eab7 100644
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ASPEED_HOST_BMC_DEV)	+= aspeed-host-bmc-dev.o
 obj-$(CONFIG_ASPEED_LPC_CTRL)		+= aspeed-lpc-ctrl.o
 obj-$(CONFIG_ASPEED_LPC_SNOOP)		+= aspeed-lpc-snoop.o
 obj-$(CONFIG_ASPEED_UART_ROUTING)	+= aspeed-uart-routing.o
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +0 -0
new file mode 100644
index 000000000000..e586d0505577

*snip*

Quoted 9 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +9 -0
+static int aspeed_pci_host_setup(struct pci_dev *pdev)
+{
+	struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
+	int rc = 0;
+
+	pci_bmc_dev->message_bar_base = pci_resource_start(pdev, 1);
+
+	if (pdev->revision == 0x27) {
+		pr_err("AST2700 detected but not supported");

drivers/soc/aspeed/aspeed-host-bmc-dev.c line 95

Quoted 10 lines
drivers/soc/aspeed/aspeed-host-bmc-dev.c new file +10 -0
+		return -ENODEV;
+	}
+
+	rc = aspeed_pci_bmc_device_setup_vuart(pdev, 0);
+	if (rc)
+		return rc;
+
+	rc = aspeed_pci_bmc_device_setup_vuart(pdev, 1);
+	if (rc)
+		goto out_free_VUART0;

This goto seems unnecessary. There's no specific cleanup that should be needed before.

Tan

Signature · 1 line
Tan Siewert <[email protected]>
#24 lore raw

PATCH v4 6/7 ARM: dts: aspeed: g6: Change vuart compatible string for ast2600

In reply to Grégoire Layet

Use the ast2600 compatible string.
Make it more precise and enable specific ast2600 properties. Still use the ast2500 compatible string as a fallback.

---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +4 -4
index 56bb3b0444f7..7c02633f2bd6 100644
@@ -707,7 +707,7 @@ emmc: sdhci@1e750100 {
 			};
 
 			vuart1: serial@1e787000 {
-				compatible = "aspeed,ast2500-vuart";
+				compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
 				reg = <0x1e787000 0x40>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
@@ -717,7 +717,7 @@ vuart1: serial@1e787000 {
 			};
 
 			vuart3: serial@1e787800 {
-				compatible = "aspeed,ast2500-vuart";
+				compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
 				reg = <0x1e787800 0x40>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
@@ -727,7 +727,7 @@ vuart3: serial@1e787800 {
 			};
 
 			vuart2: serial@1e788000 {
-				compatible = "aspeed,ast2500-vuart";
+				compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
 				reg = <0x1e788000 0x40>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
@@ -737,7 +737,7 @@ vuart2: serial@1e788000 {
 			};
 
 			vuart4: serial@1e788800 {
-				compatible = "aspeed,ast2500-vuart";
+				compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";
 				reg = <0x1e788800 0x40>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
Signature · 1 line
2.54.0
#25 lore raw

Re: [PATCH v4 6/7] ARM: dts: aspeed: g6: Change vuart compatible string for ast2600

Quoted 11 lines

Use the ast2600 compatible string.
Make it more precise and enable specific ast2600 properties. Still use the ast2500 compatible string as a fallback.

arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +0 -0
index 56bb3b0444f7..7c02633f2bd6 100644

arch/arm/boot/dts/aspeed/aspeed-g6.dtsi emmc: sdhci@1e750100 { · line 710

Quoted 5 lines
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +1 -1
@@ -707,7 +707,7 @@ emmc: sdhci@1e750100 {
 			};
 
 			vuart1: serial@1e787000 {
-				compatible = "aspeed,ast2500-vuart";
+				compatible = "aspeed,ast2600-vuart", "aspeed,ast2500-vuart";

compatible = "aspeed,ast2500-vuart", "aspeed,ast2600-vuart";

Tan

Signature · 1 line
Tan Siewert <[email protected]>
#26 lore raw

PATCH v4 7/7 ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4

In reply to Grégoire Layet

The VUART 3 and 4 are VUART over PCI.
Set this flag to indicate this information.
Also set the syscon phandle.

---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 4 ++++
 1 file changed, 4 insertions(+)
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +4 -0
index 7c02633f2bd6..2b51749300f8 100644
@@ -722,7 +722,9 @@ vuart3: serial@1e787800 {
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&syscon ASPEED_CLK_APB2>;
+				syscon = <&syscon>;
 				no-loopback-test;
+				aspeed,vuart-over-pci;
 				status = "disabled";
 			};
 
@@ -742,7 +744,9 @@ vuart4: serial@1e788800 {
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&syscon ASPEED_CLK_APB2>;
+				syscon = <&syscon>;
 				no-loopback-test;
+				aspeed,vuart-over-pci;
 				status = "disabled";
 			};
 
Signature · 1 line
2.54.0
#27 lore raw

Re: [PATCH v4 7/7] ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing 8250 port unregistration on probe error paths leads to Use-After-Free. --

--- Patch [7]: [PATCH v4 7/7] ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4 --- commit ab6072ba3517ecf2daa88b15c7fd964dcebb0912
Author: Grégoire Layet <[email protected]>

ARM: dts: aspeed: g6: add aspeed,vuart-over-pci prop to vuart3 and 4

This commit adds the aspeed,vuart-over-pci property and a syscon phandle to VUART 3 and 4 to indicate they are VUART over PCI.

arch/arm/boot/dts/aspeed/aspeed-g6.dtsi vuart3: serial@1e787800 { · line 727

Quoted 11 lines
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +2 -0
index 7c02633f2bd69..2b51749300f87 100644
@@ -722,7 +722,9 @@ vuart3: serial@1e787800 {
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&syscon ASPEED_CLK_APB2>;
+				syscon = <&syscon>;
 				no-loopback-test;
+				aspeed,vuart-over-pci;

[Severity: High]
This is a pre-existing issue, but adding this property exposes a new failure path in the driver that triggers a use-after-free.

If aspeed_ast2600_vuart_over_pci_set_enabled() fails during aspeed_vuart_probe(), the code jumps to the err_sysfs_remove label:

drivers/tty/serial/8250/8250_aspeed_vuart.c:aspeed_vuart_probe() {
...
err_sysfs_remove:

        sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
        return rc;
}

This error path returns without calling serial8250_unregister_port() or timer_delete_sync(). Because the probe failed, the devm_ framework automatically frees the vuart struct. However, the 8250 serial core still has the port registered from an earlier call to serial8250_register_8250_port(), resulting in a dangling pointer.

Could this allow a local user who opens the port to trigger a use-after-free in aspeed_vuart_startup() when it dereferences vuart->port?

Quoted 2 lines
arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +0 -0
 				status = "disabled";
 			};

[ ... ]

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7