From: sashiko-bot@kernel.org
To: "Amit Barzilai" <amit.barzilai22@gmail.com>
Cc: devicetree@vger.kernel.org, conor+dt@kernel.org,
dri-devel@lists.freedesktop.org, robh@kernel.org
Subject: Re: [PATCH 2/2] drm/solomon: Add SSD1351 OLED display driver
Date: Wed, 10 Jun 2026 16:55:41 +0000 [thread overview]
Message-ID: <20260610165541.71DCA1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260610164428.180091-3-amit.barzilai22@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Calling sleeping functions from within DRM atomic callbacks.
- [High] Passing stack-allocated variables and read-only data (.rodata) to `spi_write()`, violating the SPI subsystem's DMA-safe memory requirements.
- [High] The OLED display is not turned off when the driver module is unloaded due to `drm_dev_unplug()` preventing the `atomic_disable` hook from accessing hardware.
- [High] Coordinate space mismatch in the damage handling loop causes incorrect pixel extraction when panning.
--
commit 830ebdf4bc79cf5af84541c3dcfa33f751296ed5
Author: Amit Barzilai <amit.barzilai22@gmail.com>
drm/solomon: Add SSD1351 OLED display driver
Add a DRM/KMS driver for the Solomon SSD1351, a 128x128 65k-color RGB
OLED controller driven over a 4-wire SPI bus.
> diff --git a/drivers/gpu/drm/solomon/ssd1351.c b/drivers/gpu/drm/solomon/ssd1351.c
> new file mode 100644
> index 0000000000000..7c4a5c461afb8
> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd1351.c
[ ... ]
> +static int ssd1351_write_cmd(struct ssd1351_device *ssd1351, u8 cmd,
> + const u8 *params, size_t num)
> +{
> + int ret;
> +
> + gpiod_set_value_cansleep(ssd1351->dc, 0);
> + ret = spi_write(ssd1351->spi, &cmd, 1);
[Severity: High]
Does this code pass a stack-allocated variable to spi_write()?
The SPI subsystem requires that buffers passed to spi_write() be DMA-safe.
Since cmd is a local variable on the stack, it may not be DMA-coherent
(especially if CONFIG_VMAP_STACK is enabled). Could this trigger cache
coherency failures or memory corruption when the SPI core attempts to map it?
> + if (ret)
> + return ret;
[ ... ]
> +/* Send a command followed by a fixed list of single-byte parameters. */
> +#define ssd1351_command(ssd1351, cmd, ...) \
> + ({ \
> + static const u8 _params[] = { __VA_ARGS__ }; \
> + ssd1351_write_cmd((ssd1351), (cmd), _params, \
> + ARRAY_SIZE(_params)); \
> + })
[Severity: High]
Does this macro pass read-only data (.rodata) to spi_write() via the
_params array?
Memory placed in .rodata is not DMA-safe. If the SPI subsystem attempts to map
this buffer for a DMA transfer, could this lead to kernel panics or undefined
behavior?
[ ... ]
> +static void ssd1351_reset(struct ssd1351_device *ssd1351)
> +{
> + if (!ssd1351->reset)
> + return;
> +
> + /*
> + * Work in logical levels: 1 asserts reset, 0 releases it. The DT's
> + * GPIO_ACTIVE_LOW flag handles the physical inversion, so this pulse is
> + * correct regardless of how the board wires the RES# line.
> + */
> + gpiod_set_value_cansleep(ssd1351->reset, 1);
> + usleep_range(20, 1000);
> + gpiod_set_value_cansleep(ssd1351->reset, 0);
> + msleep(120);
> +}
[Severity: High]
Are we safely calling these sleeping functions?
This function is invoked via ssd1351_init_display() from the
ssd1351_crtc_atomic_enable() callback. According to DRM subsystem guidelines,
CRTC atomic callbacks execute in an atomic context where sleeping is strictly
forbidden. Calling msleep() and usleep_range() here could result in system
instability or deadlocks.
[ ... ]
> +static void ssd1351_fb_blit_rect(struct ssd1351_device *ssd1351,
> + struct drm_framebuffer *fb,
> + const struct iosys_map *vmap,
> + struct drm_rect *rect,
> + struct drm_format_conv_state *fmtcnv_state)
> +{
> + unsigned int width = drm_rect_width(rect);
> + unsigned int height = drm_rect_height(rect);
> + unsigned int dst_pitch = width * sizeof(u16);
> + struct iosys_map dst;
> + u8 range[2];
> +
> + iosys_map_set_vaddr(&dst, ssd1351->tx_buf);
> +
> + /*
> + * The panel expects RGB565 most-significant byte first; the big-endian
> + * conversion produces exactly that byte stream for the 8-bit SPI words.
> + */
> + drm_fb_xrgb8888_to_rgb565be(&dst, &dst_pitch, vmap, fb, rect,
> + fmtcnv_state);
> +
> + range[0] = rect->x1;
> + range[1] = rect->x2 - 1;
> + if (ssd1351_write_cmd(ssd1351, SSD1351_SET_COL_ADDRESS, range,
> + sizeof(range)))
[Severity: High]
Similar to the issue in ssd1351_write_cmd(), does this pass the
stack-allocated range array down to spi_write()? This memory may not be
DMA-coherent.
[ ... ]
> +static void ssd1351_plane_atomic_update(struct drm_plane *plane,
> + struct drm_atomic_state *state)
> +{
[ ... ]
> + if (!drm_dev_enter(&ssd1351->drm, &idx))
> + return;
> +
> + if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
> + goto out_drm_dev_exit;
> +
> + drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
> + drm_atomic_for_each_plane_damage(&iter, &damage) {
> + dst_clip = plane_state->dst;
> +
> + if (!drm_rect_intersect(&dst_clip, &damage))
> + continue;
> +
> + ssd1351_fb_blit_rect(ssd1351, fb, &shadow_plane_state->data[0],
> + &dst_clip,
> + &shadow_plane_state->fmtcnv_state);
> + }
[Severity: High]
Does this code call sleeping functions from within an atomic context?
According to DRM subsystem guidelines, plane atomic update callbacks execute
in an atomic context during non-blocking commits, where sleeping is strictly
forbidden. However, drm_gem_fb_begin_cpu_access() can block on dma-buf fences,
and ssd1351_fb_blit_rect() performs blocking SPI writes. The standard DRM
pattern for SPI displays is to defer hardware updates to a worker thread.
[Severity: High]
Does this loop also pass destination coordinates to a function expecting source
coordinates?
The helper drm_atomic_for_each_plane_damage() yields damage clips in CRTC
destination coordinates. The driver intersects these with dst_clip and passes
the result to ssd1351_fb_blit_rect(), which then passes it to
drm_fb_xrgb8888_to_rgb565be().
However, drm_fb_xrgb8888_to_rgb565be() expects the clipping rectangle to be
in framebuffer (source) coordinates to accurately extract pixels. If the
framebuffer is panned (i.e., src_x or src_y are non-zero), using destination
coordinates could extract pixels from the wrong location.
[ ... ]
> +static void ssd1351_crtc_atomic_disable(struct drm_crtc *crtc,
> + struct drm_atomic_state *state)
> +{
> + struct ssd1351_device *ssd1351 = drm_to_ssd1351(crtc->dev);
> + int idx;
> +
> + if (!drm_dev_enter(crtc->dev, &idx))
> + return;
> +
> + ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_OFF);
> +
> + drm_dev_exit(idx);
> +}
[ ... ]
> +static void ssd1351_remove(struct spi_device *spi)
> +{
> + struct drm_device *drm = spi_get_drvdata(spi);
> +
> + drm_dev_unplug(drm);
> + drm_atomic_helper_shutdown(drm);
> +}
[Severity: High]
Could the OLED display remain powered on when the driver module is unloaded?
In ssd1351_remove(), drm_dev_unplug() is called before
drm_atomic_helper_shutdown(). The drm_dev_unplug() call immediately sets the
DRM device's unplugged flag.
When drm_atomic_helper_shutdown() subsequently triggers the
ssd1351_crtc_atomic_disable() callback, the drm_dev_enter() check in that
callback will fail because the device is already marked as unplugged. As a
result, the display-off command will never be sent to the hardware.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610164428.180091-1-amit.barzilai22@gmail.com?part=2
prev parent reply other threads:[~2026-06-10 16:55 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-10 16:44 [PATCH 0/2] drm: Add driver for the Solomon SSD1351 OLED controller Amit Barzilai
2026-06-10 16:44 ` [PATCH 1/2] dt-bindings: display: Add " Amit Barzilai
2026-06-10 16:54 ` sashiko-bot
2026-06-10 16:44 ` [PATCH 2/2] drm/solomon: Add SSD1351 OLED display driver Amit Barzilai
2026-06-10 16:55 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260610165541.71DCA1F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=amit.barzilai22@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox