This series adds drivers for the NVIDIA LSTP USB adapter: a USB core driver and GPIO, LED, I2C, SPI, UART and BMC-side IPMI function drivers, with their device tree bindings, an ACPI description document and the sysfs ABI.
What LSTP is ------------ LSTP (Low-Speed Transport Protocol or Low-Speed Tunnelling Protocol) is a vendor-specific USB interface (class 0xff, subclass 0x3f) that multiplexes several low-speed "channels" over one pair of bulk endpoints. It is implemented by NVIDIA's SMA, an MCU (0955:cf11), and by other vendors' parts: two hub/bridge chips have it built in (0424:4940, 174c:2214). Boards use it to reach SPI flash, I2C sensors, GPIOs and LEDs, a UART and a host-to-BMC IPMI path, on both BMCs and host systems. The channel types are SPI host, I2C host, GPIO (with interrupts and LED pins), UART, IPMI and MMIO. Channel 0 is the control channel: at probe the driver reads the channel table from it, which gives each channel's ID, type and configuration. The set of channels is decided by the firmware, so the same VID:PID carries different channels on different boards. No firmware description is needed for the channels to work. Series layout ------------- 1 dt-bindings: gpio: Add NVIDIA LSTP GPIO 2 dt-bindings: i2c: Add NVIDIA LSTP I2C 3 dt-bindings: spi: Add NVIDIA LSTP SPI 4 dt-bindings: usb: Add NVIDIA LSTP USB adapter 5 usb: misc: Add NVIDIA LSTP USB adapter driver 6 gpio: Add NVIDIA LSTP GPIO driver 7 leds: Add NVIDIA LSTP LED driver 8 i2c: Add NVIDIA LSTP I2C driver 9 spi: Add NVIDIA LSTP SPI driver 10 tty: Add NVIDIA LSTP UART driver 11 ipmi: Add NVIDIA LSTP IPMI BMC driver Patch 4 $refs the schemas from patches 1-3, so it comes last among the bindings; it also defines the serial@N and ipmi@N channel nodes inline. The MAINTAINERS entry starts in patch 1 and gains each later patch's files. Patch 5 carries: - the core in drivers/usb/misc/; - include/linux/usb/lstp.h for the function drivers; - the sysfs ABI file; - Documentation/driver-api/usb/lstp.rst; - Documentation/firmware-guide/acpi/lstp.rst. Patches 6 and 8-11 each depend only on patch 5; patch 7 (LEDs) also needs patch 6, whose GPIO driver hands the LED pins to it. Why the auxiliary bus, and why not MFD -------------------------------------- The core binds the USB interface and owns everything shared: - URBs and packet framing; - request/response matching and the IRQ-style event path; - channel 0 discovery. Each channel the device reports is then created as an auxiliary device, lstp.<type>.<id>, and the function drivers in their subsystems bind those. They reach the device only through functions the core exports in the "LSTP" symbol namespace, such as lstp_request() and lstp_send(). The closest model in tree is LJCA (drivers/usb/misc/usb-ljca.c), and the series follows it. LJCA is a USB adapter that muxes GPIO, I2C and SPI over its bulk endpoints. At probe it asks the device which functions it has, creates one auxiliary device per reported function, and exports a transfer and an event interface to the function drivers. LSTP does the same with more channel types, with channel IDs assigned by the device firmware, and with device tree as well as ACPI. A channel has no registers, no MMIO and no interrupt lines of its own; it is a logical function of one protocol stream, and its driver needs nothing but the core's API. That is the use the auxiliary bus documentation describes (Documentation/driver-api/auxiliary_bus.rst): no dependency on a physical bus, device, register accesses or regmap. It names MFD as the wrong fit for that case, because MFD relies on the function devices being physical devices: an MFD cell is a platform device, and its resources are ranges of the parent's memory and interrupts (struct mfd_cell). Firmware matching does not decide between the two, since MFD cells can also match DT nodes and ACPI _ADR children. The same documentation says auxiliary devices "are not physical devices that are controlled by DT/ACPI". An LSTP channel is not enumerated from firmware either: it exists because the device reported it. Firmware only describes it and what is attached to it. Before auxiliary_device_add(), the core resolves each channel's node and sets it with device_set_node(): - device tree: a child of the interface node the USB core attached; - ACPI: a Device() under the interface's Device(), which is a child of the port companion (Documentation/firmware-guide/acpi/lstp.rst); - neither: the channel has no firmware node and works as reported. A channel matches on its address (reg, or _ADR on ACPI) plus compatible. The I2C, SPI and GPIO cores then enumerate children and resolve references as for any other controller. The UART: a plain tty_driver (patch 10) --------------------------------------- The firmware owns the UART line: baud rate, framing, parity and flow control are provisioned on the device and only read at probe. The host cannot read or set modem control lines; it can send a fixed-length break, and a carrier loss reported by the device hangs the tty up unless CLOCAL is set. Most of serial_core's uart_ops would be stubs, and usb-serial does not fit because it binds the whole USB interface, where the UART is one function among several. So patch 10 registers a plain tty_driver (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV) with one tty_port per channel, the structure cdc-acm uses for a UART behind USB. set_termios keeps the hardware fields at the firmware's values, so stty reports the real line settings. The nodes are /dev/ttyLSTP<n>, parented on the channel's auxiliary device. Jiri, Ilpo: if you would rather see this on serial_core despite the empty uart_ops, please say so on patch 10. The IPMI channel: BMC side, with a message number (patch 11) ------------------------------------------------------------ On a BMC, the IPMI channel carries the host's IPMI requests to BMC userspace and the responses back, like ssif_bmc does for SSIF; it is not an SSIF transport and has no host-side (ipmi_si) part. Each channel is a character device, /dev/ipmi-lstp<n>. By default, each message on that node carries a one-byte message number between the length and the payload, and a response must echo the number of the request it answers. The number exists only on the node, not in the LSTP protocol, and no other BMC-side IPMI driver has it. It names the request a response is for: when the host has sent a newer request, a late response to the older one is dropped, even if userspace has already read the newer request. Without the number, a response answers the request read last. With CONFIG_USB_LSTP_IPMI_MSG_NUM=n the node uses ssif_bmc's struct ipmi_ssif_msg layout instead, so userspace written for ssif_bmc works unchanged. Corey: is the message-number layout acceptable as an LSTP-specific extension, or would you prefer it as an option of the generic BMC message format (and ssif_bmc)? Responses carry no tag ---------------------- The protocol has no request tag: the first response after a request is its answer. Two places in the series depend on that: - The core (patch 5) drops a response that arrives when no request is waiting, or after the waiting request already has its answer, and counts it in the channel's rx_late statistic. A surplus response (a reply to a request that timed out, one left from before a rebind, or a device answering twice) therefore cannot overwrite a response the waiter is still reading. - The GPIO driver (patch 6) reads every pin's interrupt configuration at probe. A late reply can answer the next request and shift every later pin's state by one, so a single read is not retried on its own: after a timeout, all pins are read again, in alternating order, until two consecutive passes without a timeout agree. That is at most five passes, ending within 10 s of the first timeout, or the probe fails as it would without the re-read. The bound is there because the probe runs in the context that added the device, often the hub's worker. The DT nodes for IPMI and UART channels --------------------------------------- The USB binding (patch 4) defines serial@N and ipmi@N channel nodes with only compatible, reg and status. They exist for status = "disabled", which stops a channel the firmware reports from being created on a board where it must not be exposed. Without a node, a channel is still created. The binding shape, including one vendor property (nvidia,retries on the I2C channel), is discussed in a separate mail to the DT maintainers sent with this series: https://lore.kernel.org/r/[email protected] What is not in this series -------------------------- - The MMIO channel stays out of tree: raw register access, with no binding and no kernel consumer. - No auto-created spidev. The out-of-tree driver has a module parameter that creates a spidev on every chip select of an undescribed SPI channel; it is not part of this series. With CONFIG_SPI_DYNAMIC, userspace does that through the controller's new_device attribute: echo "spidev <cs>" > /sys/class/spi_master/spi<B>/new_device (Documentation/ABI/testing/sysfs-class-spi-master) - No separate IPMI POST-code node and no debug fault injection; both stay in the out-of-tree package. Testing ------- The drivers were tested on arm64 and x86_64 with four kinds of device: - real endpoints, the SMA and other vendors' implementations, driven by the hardware test suite of the out-of-tree package on Raspberry Pi hosts; - a real SMA passed through over USB to QEMU guests running v7.3-rc5 with this series; - an emulated endpoint, a raw-gadget program on dummy_hcd, playing scripted protocol scenarios; - the same emulator mutating its replies at random. The test plan covers: - every channel type end to end: SPI flash identification, write and read-back verification and throughput through spidev; I2C transfers; GPIO values, interrupts, line names and hogs; LED default states, brightness and hardware patterns; UART and IPMI traffic; concurrent traffic on all channels; - firmware descriptions: ACPI SSDTs and device tree overlays in many variants, including incomplete, mismatched and outdated ones; - lifetime: channel driver, USB interface and module unbind, rebind and removal, USB disconnect and reset, with nodes open and consumers attached, under load, and with nodes opened as soon as they appear; - protocol faults: late, duplicate, missing and malformed replies, and a disconnect in the middle of a transfer; - allocation failures injected across the interface bind and unbind, the function driver probes, open, read and module load. The kernels used KASAN with kmemleak, KCSAN and KMSAN; lockdep with PROVE_RCU, DEBUG_OBJECTS, DEBUG_LIST, DEBUG_KOBJECT_RELEASE, DEBUG_ATOMIC_SLEEP and UBSAN; and failslab, fail_page_alloc and fail-nth for fault injection. None of them reported a problem in these drivers. The only reports involving them came from gpiolib when a GPIO chip is removed with lines still requested; the fixes are posted separately: https://lore.kernel.org/r/[email protected] Per patch, on the posted base: each patch builds (allmodconfig, W=1, LSTP objects) on x86_64 with gcc and clang and on arm64 and arm with gcc; sparse; kernel-doc; checkpatch --strict (clean apart from two MACRO_ARG_REUSE checks in patch 5); dt_binding_check on each binding; make htmldocs adds no warnings. The out-of-tree package these drivers come from is at https://github.com/NVIDIA/lstp_module; the version these patches match is the public-next-v1 tag: https://github.com/NVIDIA/lstp_module/tree/public-next-v1 It stays as the backport for kernels without this series. Base: usb-next at bbf6b99a57b2 ("usb: typec: ucsi_ccg: Add retry mechanism in ccg_read"). Adrian Ambrozewicz (11): dt-bindings: gpio: Add NVIDIA LSTP GPIO dt-bindings: i2c: Add NVIDIA LSTP I2C dt-bindings: spi: Add NVIDIA LSTP SPI dt-bindings: usb: Add NVIDIA LSTP USB adapter usb: misc: Add NVIDIA LSTP USB adapter driver gpio: Add NVIDIA LSTP GPIO driver leds: Add NVIDIA LSTP LED driver i2c: Add NVIDIA LSTP I2C driver spi: Add NVIDIA LSTP SPI driver tty: Add NVIDIA LSTP UART driver ipmi: Add NVIDIA LSTP IPMI BMC driver .../ABI/testing/sysfs-bus-usb-devices-lstp | 331 ++ .../bindings/gpio/nvidia,lstp-gpio.yaml | 276 ++ .../bindings/i2c/nvidia,lstp-i2c.yaml | 71 + .../bindings/spi/nvidia,lstp-spi.yaml | 68 + .../devicetree/bindings/usb/nvidia,lstp.yaml | 280 ++ Documentation/driver-api/usb/index.rst | 1 + Documentation/driver-api/usb/lstp.rst | 276 ++ Documentation/firmware-guide/acpi/index.rst | 1 + Documentation/firmware-guide/acpi/lstp.rst | 419 +++ MAINTAINERS | 21 + drivers/char/ipmi/Kconfig | 32 + drivers/char/ipmi/Makefile | 1 + drivers/char/ipmi/ipmi-lstp.c | 464 +++ drivers/gpio/Kconfig | 14 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-lstp.c | 1194 +++++++ drivers/i2c/busses/Kconfig | 13 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-lstp.c | 573 ++++ drivers/leds/Kconfig | 14 + drivers/leds/Makefile | 1 + drivers/leds/leds-lstp.c | 404 +++ drivers/spi/Kconfig | 13 + drivers/spi/Makefile | 1 + drivers/spi/spi-lstp.c | 316 ++ drivers/tty/Kconfig | 13 + drivers/tty/Makefile | 1 + drivers/tty/lstp_tty.c | 829 +++++ drivers/usb/misc/Kconfig | 15 + drivers/usb/misc/Makefile | 1 + drivers/usb/misc/lstp.c | 2983 +++++++++++++++++ include/linux/usb/lstp.h | 219 ++ 32 files changed, 8847 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-usb-devices-lstp create mode 100644 Documentation/devicetree/bindings/gpio/nvidia,lstp-gpio.yaml create mode 100644 Documentation/devicetree/bindings/i2c/nvidia,lstp-i2c.yaml create mode 100644 Documentation/devicetree/bindings/spi/nvidia,lstp-spi.yaml create mode 100644 Documentation/devicetree/bindings/usb/nvidia,lstp.yaml create mode 100644 Documentation/driver-api/usb/lstp.rst create mode 100644 Documentation/firmware-guide/acpi/lstp.rst create mode 100644 drivers/char/ipmi/ipmi-lstp.c create mode 100644 drivers/gpio/gpio-lstp.c create mode 100644 drivers/i2c/busses/i2c-lstp.c create mode 100644 drivers/leds/leds-lstp.c create mode 100644 drivers/spi/spi-lstp.c create mode 100644 drivers/tty/lstp_tty.c create mode 100644 drivers/usb/misc/lstp.c create mode 100644 include/linux/usb/lstp.h base-commit: bbf6b99a57b2479bf51c3c8ad0946f4b8c33ed69 -- 2.43.0 _______________________________________________ Openipmi-developer mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openipmi-developer
