Re: [PATCH 2/2] backlight: Add support for Orient Chip OCP8178
[email protected] Thu, 06 Aug 2026 20:36:53 +0000
| Newsgroups | org.kernel.vger.linux-leds,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-devicetree |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [High] Restoring interrupts while the GPIO is driven low exposes the End-Of-Sequence pulse to arbitrary timing extension. - [High] The driver calls `gpiod_set_value()` inside an atomic section without verifying if the GPIO can sleep. - [Medium] Missing onewire protocol re-initialization on system resume. - [Medium] The protocol transaction is split across multiple atomic sections, exposing the inter-byte gap to interrupt latency. -- --- Patch [2]: [PATCH 2/2] backlight: Add support for Orient Chip OCP8178 --- commit a17d436f493c13ff679b7f63c64445e13b71e314 Author: Wim de With <[email protected]> backlight: Add support for Orient Chip OCP8178 Add a driver for the Orient Chip OCP8178 backlight controller. The OCP8178 supports either PWM or a vendor-specific onewire protocol over GPIO. This driver implements the single-wire protocol, which enables setting static brightness levels without requiring a continuous PWM signal from the host CPU. > diff --git a/drivers/video/backlight/ocp8178_bl.c b/drivers/video/backlight/ocp8178_bl.c > new file mode 100644 > --- /dev/null > +++ b/drivers/video/backlight/ocp8178_bl.c [ ... ] > +static void ocp8178_bl_write_u8(struct ocp8178_bl *ocp8178, u8 value) > +{ > + unsigned long flags; > + > + gpiod_set_value(ocp8178->gpiod, 1); > + udelay(OCP8178_1W_T_START_US); > + > + local_irq_save(flags); > + > + for (int i = 7; i >= 0; i--) { > + if ((value >> i) & 1) { > + gpiod_set_value(ocp8178->gpiod, 0); [Severity: High] Could this trigger a scheduling while atomic bug if the GPIO controller is behind an I2C or SPI expander? Since this bit-banging occurs inside a local_irq_save() block where hardware interrupts are disabled, any GPIO accesses must not sleep. If the driver is instantiated via Device Tree with a sleepable GPIO, gpiod_set_value() will attempt to sleep in an atomic context. Should probe() explicitly reject sleepable GPIOs by checking gpiod_cansleep()? > + udelay(OCP8178_1W_HIGH_BIT_T_LOW_US); > + gpiod_set_value(ocp8178->gpiod, 1); > + udelay(OCP8178_1W_HIGH_BIT_T_HIGH_US); > + } else { > + gpiod_set_value(ocp8178->gpiod, 0); > + udelay(OCP8178_1W_LOW_BIT_T_LOW_US); > + gpiod_set_value(ocp8178->gpiod, 1); > + udelay(OCP8178_1W_LOW_BIT_T_HIGH_US); > + } > + } > + > + gpiod_set_value(ocp8178->gpiod, 0); > + > + local_irq_restore(flags); > + > + udelay(OCP8178_1W_T_EOS_US); > + gpiod_set_value(ocp8178->gpiod, 1); [Severity: High] Is there a risk that the end-of-sequence pulse gets extended arbitrarily here? By calling local_irq_restore() while the GPIO is driven low, any pending interrupts will run immediately. If system interrupt processing or softirqs delay execution by more than 2.5ms (OCP8178_T_OFF_MS), the hardware will interpret this extended low pulse as a command to disable the onewire mode. This could cause the controller to unexpectedly power off and revert to PWM mode, breaking backlight control. Would it be safer to restore interrupts after the final gpiod_set_value() call? > +} > + > +static void ocp8178_bl_set_brightness(struct ocp8178_bl *ocp8178, u8 brightness) > +{ > + u8 data = 0; > + > + dev_dbg(ocp8178->dev, "setting brightness to %u\n", brightness); > + > + data |= FIELD_PREP(OCP8178_DATA_ADDR, 0); > + data |= FIELD_PREP(OCP8178_DATA_VALUE, brightness); > + > + ocp8178_bl_write_u8(ocp8178, OCP8178_DEVICE_ADDRESS); > + ocp8178_bl_write_u8(ocp8178, data); [Severity: Medium] Does the controller require strict timing between the address and data bytes? Since ocp8178_bl_write_u8() only disables interrupts for the duration of a single byte, an interrupt could fire between these two calls. If the 1-wire hardware state machine has a maximum idle time, arbitrary interrupt latency in the inter-byte gap might cause the controller to reset and drop the brightness update. > +} [ ... ] > +static const struct backlight_ops ocp8178_bl_ops = { > + .options = BL_CORE_SUSPENDRESUME, > + .update_status = ocp8178_bl_update_status, > +}; [Severity: Medium] Is BL_CORE_SUSPENDRESUME sufficient for restoring this hardware after suspend? If the platform cuts power to the backlight controller during system suspend, the hardware will wake up in its default PWM mode. The backlight core will simply call update_status() on resume to restore brightness, but the onewire brightness commands will be ignored because the onewire mode hasn't been re-enabled. Should the platform driver provide pm operations to re-execute ocp8178_bl_enable_onewire() on system resume? [ ... ] > + ocp8178->gpiod = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); > + if (IS_ERR(ocp8178->gpiod)) > + return dev_err_probe(dev, PTR_ERR(ocp8178->gpiod), > + "gpio missing or invalid\n"); [Severity: High] As mentioned above, since the driver requires microsecond precision bit-banging in an atomic context, should we check gpiod_cansleep() here and fail probe if the GPIO requires sleeping? [ ... ] -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2