* [PATCH v3] drm/gud: move format init from gud_probe()
[not found] <20261026210116.10082-1-rubenru09.ref@aol.com>
@ 2026-10-26 21:00 ` Ruben Wauters
2026-10-26 21:07 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Ruben Wauters @ 2026-10-26 21:00 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Ruben Wauters, dri-devel, linux-kernel
As part of the cleanup of gud_probe(), this patch splits off format init
code from gud_probe into it's own function. This makes the code more
compartmentalised and easier to follow, and makes gud_probe() smaller
and also easier to read.
Signed-off-by: Ruben Wauters <rubenru09@aol.com>
---
V1 -> V2:
- Removed output parameters for gud_get_formats()
- Added gud_get_max_buffer_size() helper function
Apologies this v2 took so long
V2 -> V3:
- Fix potential num_formats underflow
- Skip XRGB8888 in size calculations if emulated
- Remove redundant r1 and XRGB1111 size calculations
---
---
drivers/gpu/drm/gud/gud_drv.c | 185 ++++++++++++++++++++--------------
1 file changed, 111 insertions(+), 74 deletions(-)
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 680447f426f3..36adf2e2b6a2 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -435,11 +435,115 @@ static void gud_free_buffers_and_mutex(void *data)
mutex_destroy(&gdrm->ctrl_lock);
}
-static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static size_t gud_get_max_buffer_size(struct gud_device *gdrm, u32 *formats, u32 num_formats)
+{
+ struct drm_device *drm = &gdrm->drm;
+ size_t max_buffer_size = 0;
+ size_t fmt_buf_size;
+ int i;
+
+ for (i = 0; i < num_formats; i++) {
+ const struct drm_format_info *info = drm_format_info(formats[i]);
+
+ /* Skip over emulated XRGB8888 */
+ if (formats[i] == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
+ continue;
+
+ fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
+ drm->mode_config.max_height;
+ max_buffer_size = max(max_buffer_size, fmt_buf_size);
+ }
+
+ return max_buffer_size;
+}
+
+static int gud_get_formats(struct gud_device *gdrm, u32 *formats)
{
const struct drm_format_info *xrgb8888_emulation_format = NULL;
bool rgb565_supported = false, xrgb8888_supported = false;
unsigned int num_formats_dev, num_formats = 0;
+ u8 *formats_dev;
+ struct drm_device *drm = &gdrm->drm;
+ struct device *usb_device = gdrm->drm.dev;
+ int ret, i;
+
+ formats_dev = devm_kmalloc(usb_device, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
+ if (!formats_dev)
+ return -ENOMEM;
+
+ ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, GUD_FORMATS_MAX_NUM);
+ if (ret < 0)
+ return ret;
+
+ num_formats_dev = ret;
+ for (i = 0; i < num_formats_dev; i++) {
+ const struct drm_format_info *info;
+ u32 format;
+
+ format = gud_to_fourcc(formats_dev[i]);
+ if (!format) {
+ drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]);
+ continue;
+ }
+
+ if (format == GUD_DRM_FORMAT_R1)
+ info = &gud_drm_format_r1;
+ else if (format == GUD_DRM_FORMAT_XRGB1111)
+ info = &gud_drm_format_xrgb1111;
+ else
+ info = drm_format_info(format);
+
+ switch (format) {
+ case GUD_DRM_FORMAT_R1:
+ fallthrough;
+ case DRM_FORMAT_R8:
+ fallthrough;
+ case GUD_DRM_FORMAT_XRGB1111:
+ fallthrough;
+ case DRM_FORMAT_RGB332:
+ fallthrough;
+ case DRM_FORMAT_RGB888:
+ if (!xrgb8888_emulation_format)
+ xrgb8888_emulation_format = info;
+ break;
+ case DRM_FORMAT_RGB565:
+ rgb565_supported = true;
+ if (!xrgb8888_emulation_format)
+ xrgb8888_emulation_format = info;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ xrgb8888_supported = true;
+ break;
+ }
+
+ if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
+ continue; /* Internal not for userspace */
+
+ formats[num_formats++] = format;
+ }
+
+ if (!num_formats && !xrgb8888_emulation_format) {
+ dev_err(usb_device, "No supported pixel formats found\n");
+ return -EINVAL;
+ }
+
+ /* Prefer speed over color depth */
+ if (rgb565_supported)
+ drm->mode_config.preferred_depth = 16;
+
+ if (!xrgb8888_supported && xrgb8888_emulation_format) {
+ gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
+ formats[num_formats++] = DRM_FORMAT_XRGB8888;
+ }
+
+ devm_kfree(usb_device, formats_dev);
+
+ return num_formats;
+}
+
+static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ int num_formats = 0;
struct usb_endpoint_descriptor *bulk_out;
struct gud_display_descriptor_req desc;
struct device *dev = &intf->dev;
@@ -447,9 +551,8 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct gud_device *gdrm;
struct drm_device *drm;
struct device *dma_dev;
- u8 *formats_dev;
u32 *formats;
- int ret, i;
+ int ret;
ret = usb_find_bulk_out_endpoint(intf->cur_altsetting, &bulk_out);
if (ret)
@@ -510,81 +613,16 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
drm->mode_config.helper_private = &gud_mode_config_helpers;
/* Format init */
- formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
/* Add room for emulated XRGB8888 */
formats = devm_kmalloc_array(dev, GUD_FORMATS_MAX_NUM + 1, sizeof(*formats), GFP_KERNEL);
- if (!formats_dev || !formats)
+ if (!formats)
return -ENOMEM;
- ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, GUD_FORMATS_MAX_NUM);
- if (ret < 0)
- return ret;
-
- num_formats_dev = ret;
- for (i = 0; i < num_formats_dev; i++) {
- const struct drm_format_info *info;
- size_t fmt_buf_size;
- u32 format;
-
- format = gud_to_fourcc(formats_dev[i]);
- if (!format) {
- drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]);
- continue;
- }
-
- if (format == GUD_DRM_FORMAT_R1)
- info = &gud_drm_format_r1;
- else if (format == GUD_DRM_FORMAT_XRGB1111)
- info = &gud_drm_format_xrgb1111;
- else
- info = drm_format_info(format);
-
- switch (format) {
- case GUD_DRM_FORMAT_R1:
- fallthrough;
- case DRM_FORMAT_R8:
- fallthrough;
- case GUD_DRM_FORMAT_XRGB1111:
- fallthrough;
- case DRM_FORMAT_RGB332:
- fallthrough;
- case DRM_FORMAT_RGB888:
- if (!xrgb8888_emulation_format)
- xrgb8888_emulation_format = info;
- break;
- case DRM_FORMAT_RGB565:
- rgb565_supported = true;
- if (!xrgb8888_emulation_format)
- xrgb8888_emulation_format = info;
- break;
- case DRM_FORMAT_XRGB8888:
- xrgb8888_supported = true;
- break;
- }
-
- fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
- drm->mode_config.max_height;
- max_buffer_size = max(max_buffer_size, fmt_buf_size);
-
- if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
- continue; /* Internal not for userspace */
-
- formats[num_formats++] = format;
- }
+ num_formats = gud_get_formats(gdrm, formats);
+ if (num_formats <= 0)
+ return num_formats;
- if (!num_formats && !xrgb8888_emulation_format) {
- dev_err(dev, "No supported pixel formats found\n");
- return -EINVAL;
- }
-
- /* Prefer speed over color depth */
- if (rgb565_supported)
- drm->mode_config.preferred_depth = 16;
-
- if (!xrgb8888_supported && xrgb8888_emulation_format) {
- gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
- formats[num_formats++] = DRM_FORMAT_XRGB8888;
- }
+ max_buffer_size = gud_get_max_buffer_size(gdrm, formats, num_formats);
if (desc.max_buffer_size)
max_buffer_size = le32_to_cpu(desc.max_buffer_size);
@@ -650,7 +688,6 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
return ret;
devm_kfree(dev, formats);
- devm_kfree(dev, formats_dev);
drm_client_setup(drm, NULL);
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v3] drm/gud: move format init from gud_probe()
2026-10-26 21:00 ` [PATCH v3] drm/gud: move format init from gud_probe() Ruben Wauters
@ 2026-10-26 21:07 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-26 21:07 UTC (permalink / raw)
To: Ruben Wauters; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] drm/gud: zero max_buffer_size in gud_get_max_buffer_size() for R1/XRGB1111
--
commit 9571a61953c7bcaa943faf581ba726cb4c44a2b4
Author: Ruben Wauters <rubenru09@aol.com>
drm/gud: move format init from gud_probe()
This patch factors pixel format initialization and maximum buffer size
calculation out of gud_probe() into helper functions gud_get_formats() and
gud_get_max_buffer_size().
> diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
> index 680447f426f37..36adf2e2b6a2e 100644
> --- a/drivers/gpu/drm/gud/gud_drv.c
> +++ b/drivers/gpu/drm/gud/gud_drv.c
> @@ -435,11 +435,115 @@ static void gud_free_buffers_and_mutex(void *data)
> mutex_destroy(&gdrm->ctrl_lock);
> }
>
> -static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
> +static size_t gud_get_max_buffer_size(struct gud_device *gdrm, u32 *formats, u32 num_formats)
> +{
> + struct drm_device *drm = &gdrm->drm;
> + size_t max_buffer_size = 0;
> + size_t fmt_buf_size;
> + int i;
> +
> + for (i = 0; i < num_formats; i++) {
> + const struct drm_format_info *info = drm_format_info(formats[i]);
> +
> + /* Skip over emulated XRGB8888 */
> + if (formats[i] == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
> + continue;
> +
> + fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
> + drm->mode_config.max_height;
> + max_buffer_size = max(max_buffer_size, fmt_buf_size);
> + }
> +
> + return max_buffer_size;
> +}
[Severity: High]
Could skipping emulated DRM_FORMAT_XRGB8888 in gud_get_max_buffer_size()
cause max_buffer_size to be calculated as 0 when a device only supports
internal formats (GUD_DRM_FORMAT_R1 or GUD_DRM_FORMAT_XRGB1111)?
In gud_get_formats(), GUD_DRM_FORMAT_R1 and GUD_DRM_FORMAT_XRGB1111 set
xrgb8888_emulation_format to &gud_drm_format_r1 or &gud_drm_format_xrgb1111,
and are then skipped before being added to formats[]:
if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
continue; /* Internal not for userspace */
formats[num_formats++] = format;
If the device only advertises GUD_PIXEL_FORMAT_R1 and/or
GUD_PIXEL_FORMAT_XRGB1111, num_formats remains 0 after the loop and
gud_get_formats() appends DRM_FORMAT_XRGB8888 as the sole entry in
formats[]:
if (!xrgb8888_supported && xrgb8888_emulation_format) {
gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
formats[num_formats++] = DRM_FORMAT_XRGB8888;
}
Previously, gud_probe() computed fmt_buf_size inside the formats_dev loop
before skipping R1 and XRGB1111, so their buffer sizes were accounted for.
With this change, gud_get_max_buffer_size() skips the only entry in
formats[] and returns 0. When the optional desc.max_buffer_size descriptor
field is 0, gud_probe() sets gdrm->bulk_len = 0 and calls
gud_alloc_bulk_buffer():
gud_probe()
gud_alloc_bulk_buffer()
vmalloc_32(gdrm->bulk_len)
Passing 0 to vmalloc_32() triggers WARN_ON_ONCE(!size) and returns NULL,
causing gud_probe() to fail with -ENOMEM.
Should gud_get_max_buffer_size() substitute gdrm->xrgb8888_emulation_format
for info when formats[i] == DRM_FORMAT_XRGB8888 and
gdrm->xrgb8888_emulation_format is set, instead of skipping it?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261026210116.10082-1-rubenru09@aol.com?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-26 21:07 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261026210116.10082-1-rubenru09.ref@aol.com>
2026-10-26 21:00 ` [PATCH v3] drm/gud: move format init from gud_probe() Ruben Wauters
2026-10-26 21:07 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.