mirror of
https://github.com/torvalds/linux.git
synced 2026-10-26 20:46:02 +01:00
drm/vkms: Move frame_info into vkms_plane_state
The vkms_frame_info structure is allocated separately in vkms_plane_duplicate_state() and freed in vkms_plane_destroy_state(), but has the exact same lifetime as the vkms_plane_state that contains it. This separate allocation is fragile: frame_info is only allocated in duplicate_state, so any other path that creates a vkms_plane_state produces a state with a NULL frame_info pointer. Both vkms_plane_atomic_update() and vkms_plane_destroy_state() dereference it unconditionally when a CRTC is set. Embed frame_info directly in vkms_plane_state. The structure is zero-initialized as part of the kzalloc, removing the need for a separate allocation and its error handling in duplicate_state, and the matching kfree in destroy_state. Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20260908-drm-no-more-plane-reset-v4-2-a31b3fcfc989@kernel.org Signed-off-by: Maxime Ripard <mripard@kernel.org>
This commit is contained in:
parent
8c733e74ad
commit
d1efdf6c84
|
|
@ -311,7 +311,7 @@ static void clamp_line_coordinates(enum pixel_read_direction direction,
|
|||
/* By default the start points are correct */
|
||||
*src_x_start = src_line->x1;
|
||||
*src_y_start = src_line->y1;
|
||||
*dst_x_start = current_plane->frame_info->dst.x1;
|
||||
*dst_x_start = current_plane->frame_info.dst.x1;
|
||||
|
||||
/* Get the correct number of pixel to blend, it depends of the direction */
|
||||
switch (direction) {
|
||||
|
|
@ -339,8 +339,8 @@ static void clamp_line_coordinates(enum pixel_read_direction direction,
|
|||
*dst_x_start -= *src_x_start;
|
||||
*src_x_start = 0;
|
||||
}
|
||||
if (*src_x_start + *pixel_count > current_plane->frame_info->fb->width)
|
||||
*pixel_count = max(0, (int)current_plane->frame_info->fb->width -
|
||||
if (*src_x_start + *pixel_count > current_plane->frame_info.fb->width)
|
||||
*pixel_count = max(0, (int)current_plane->frame_info.fb->width -
|
||||
*src_x_start);
|
||||
break;
|
||||
case READ_BOTTOM_TO_TOP:
|
||||
|
|
@ -350,8 +350,8 @@ static void clamp_line_coordinates(enum pixel_read_direction direction,
|
|||
*dst_x_start -= *src_y_start;
|
||||
*src_y_start = 0;
|
||||
}
|
||||
if (*src_y_start + *pixel_count > current_plane->frame_info->fb->height)
|
||||
*pixel_count = max(0, (int)current_plane->frame_info->fb->height -
|
||||
if (*src_y_start + *pixel_count > current_plane->frame_info.fb->height)
|
||||
*pixel_count = max(0, (int)current_plane->frame_info.fb->height -
|
||||
*src_y_start);
|
||||
break;
|
||||
}
|
||||
|
|
@ -374,8 +374,8 @@ static void blend_line(struct vkms_plane_state *current_plane, int y,
|
|||
struct drm_rect dst_line, tmp_src, src_line;
|
||||
|
||||
/* Avoid rendering useless lines */
|
||||
if (y < current_plane->frame_info->dst.y1 ||
|
||||
y >= current_plane->frame_info->dst.y2)
|
||||
if (y < current_plane->frame_info.dst.y1 ||
|
||||
y >= current_plane->frame_info.dst.y2)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
@ -383,11 +383,11 @@ static void blend_line(struct vkms_plane_state *current_plane, int y,
|
|||
* destination framebuffer, and then drm_rect_* helpers are used to
|
||||
* compute the correct position into the source framebuffer.
|
||||
*/
|
||||
dst_line = DRM_RECT_INIT(current_plane->frame_info->dst.x1, y,
|
||||
drm_rect_width(¤t_plane->frame_info->dst),
|
||||
dst_line = DRM_RECT_INIT(current_plane->frame_info.dst.x1, y,
|
||||
drm_rect_width(¤t_plane->frame_info.dst),
|
||||
1);
|
||||
|
||||
drm_rect_fp_to_int(&tmp_src, ¤t_plane->frame_info->src);
|
||||
drm_rect_fp_to_int(&tmp_src, ¤t_plane->frame_info.src);
|
||||
|
||||
/*
|
||||
* [1]: Clamping src_line to the crtc_x_limit to avoid writing outside of
|
||||
|
|
@ -411,17 +411,17 @@ static void blend_line(struct vkms_plane_state *current_plane, int y,
|
|||
* same size, but can be rotated).
|
||||
* - Apply the offset of the source rectangle to the coordinate.
|
||||
*/
|
||||
drm_rect_translate(&src_line, -current_plane->frame_info->dst.x1,
|
||||
-current_plane->frame_info->dst.y1);
|
||||
drm_rect_translate(&src_line, -current_plane->frame_info.dst.x1,
|
||||
-current_plane->frame_info.dst.y1);
|
||||
drm_rect_rotate_inv(&src_line, drm_rect_width(&tmp_src),
|
||||
drm_rect_height(&tmp_src),
|
||||
current_plane->frame_info->rotation);
|
||||
current_plane->frame_info.rotation);
|
||||
drm_rect_translate(&src_line, tmp_src.x1, tmp_src.y1);
|
||||
|
||||
/* Get the correct reading direction in the source buffer. */
|
||||
|
||||
enum pixel_read_direction direction =
|
||||
direction_for_rotation(current_plane->frame_info->rotation);
|
||||
direction_for_rotation(current_plane->frame_info.rotation);
|
||||
|
||||
/* [2]: Compute and clamp the number of pixel to read */
|
||||
clamp_line_coordinates(direction, current_plane, &src_line, &src_x_start, &src_y_start,
|
||||
|
|
@ -539,7 +539,7 @@ static int check_iosys_map(struct vkms_crtc_state *crtc_state)
|
|||
u32 n_active_planes = crtc_state->num_active_planes;
|
||||
|
||||
for (size_t i = 0; i < n_active_planes; i++)
|
||||
if (iosys_map_is_null(&plane_state[i]->frame_info->map[0]))
|
||||
if (iosys_map_is_null(&plane_state[i]->frame_info.map[0]))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ struct conversion_matrix {
|
|||
*/
|
||||
struct vkms_plane_state {
|
||||
struct drm_shadow_plane_state base;
|
||||
struct vkms_frame_info *frame_info;
|
||||
struct vkms_frame_info frame_info;
|
||||
pixel_read_line_t pixel_read_line;
|
||||
struct conversion_matrix conversion_matrix;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -321,10 +321,10 @@ static void function_name(const struct vkms_plane_state *plane, int x_start, \
|
|||
struct pixel_argb_u16 out_pixel[]) \
|
||||
{ \
|
||||
struct pixel_argb_u16 *end = out_pixel + count; \
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
|
||||
int step = get_block_step_bytes(plane->frame_info.fb, direction, 0); \
|
||||
u8 *src_pixels; \
|
||||
\
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels); \
|
||||
packed_pixels_addr_1x1(&plane->frame_info, x_start, y_start, 0, &src_pixels); \
|
||||
\
|
||||
while (out_pixel < end) { \
|
||||
pixel_type *(pixel_name) = (pixel_type *)src_pixels; \
|
||||
|
|
@ -379,16 +379,16 @@ static void Rx_read_line(const struct vkms_plane_state *plane, int x_start,
|
|||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
int bits_per_pixel = drm_format_info_bpp(plane->frame_info->fb->format, 0);
|
||||
int bits_per_pixel = drm_format_info_bpp(plane->frame_info.fb->format, 0);
|
||||
u8 *src_pixels;
|
||||
int rem_x, rem_y;
|
||||
|
||||
WARN_ONCE(drm_format_info_block_height(plane->frame_info->fb->format, 0) != 1,
|
||||
WARN_ONCE(drm_format_info_block_height(plane->frame_info.fb->format, 0) != 1,
|
||||
"%s() only support formats with block_h == 1", __func__);
|
||||
|
||||
packed_pixels_addr(plane->frame_info, x_start, y_start, 0, &src_pixels, &rem_x, &rem_y);
|
||||
packed_pixels_addr(&plane->frame_info, x_start, y_start, 0, &src_pixels, &rem_x, &rem_y);
|
||||
int bit_offset = (8 - bits_per_pixel) - rem_x * bits_per_pixel;
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
int step = get_block_step_bytes(plane->frame_info.fb, direction, 0);
|
||||
int mask = (0x1 << bits_per_pixel) - 1;
|
||||
int lum_per_level = 0xFFFF / mask;
|
||||
|
||||
|
|
@ -503,15 +503,15 @@ static void function_name(const struct vkms_plane_state *plane, int x_start, \
|
|||
u8 *plane_1; \
|
||||
u8 *plane_2; \
|
||||
\
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, \
|
||||
packed_pixels_addr_1x1(&plane->frame_info, x_start, y_start, 0, \
|
||||
&plane_1); \
|
||||
packed_pixels_addr_1x1(plane->frame_info, \
|
||||
x_start / plane->frame_info->fb->format->hsub, \
|
||||
y_start / plane->frame_info->fb->format->vsub, 1, \
|
||||
packed_pixels_addr_1x1(&plane->frame_info, \
|
||||
x_start / plane->frame_info.fb->format->hsub, \
|
||||
y_start / plane->frame_info.fb->format->vsub, 1, \
|
||||
&plane_2); \
|
||||
int step_1 = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
|
||||
int step_2 = get_block_step_bytes(plane->frame_info->fb, direction, 1); \
|
||||
int subsampling = get_subsampling(plane->frame_info->fb->format, direction); \
|
||||
int step_1 = get_block_step_bytes(plane->frame_info.fb, direction, 0); \
|
||||
int step_2 = get_block_step_bytes(plane->frame_info.fb, direction, 1); \
|
||||
int subsampling = get_subsampling(plane->frame_info.fb->format, direction); \
|
||||
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); \
|
||||
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix; \
|
||||
\
|
||||
|
|
@ -548,20 +548,20 @@ static void planar_yuv_read_line(const struct vkms_plane_state *plane, int x_sta
|
|||
u8 *channel_1_plane;
|
||||
u8 *channel_2_plane;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0,
|
||||
packed_pixels_addr_1x1(&plane->frame_info, x_start, y_start, 0,
|
||||
&y_plane);
|
||||
packed_pixels_addr_1x1(plane->frame_info,
|
||||
x_start / plane->frame_info->fb->format->hsub,
|
||||
y_start / plane->frame_info->fb->format->vsub, 1,
|
||||
packed_pixels_addr_1x1(&plane->frame_info,
|
||||
x_start / plane->frame_info.fb->format->hsub,
|
||||
y_start / plane->frame_info.fb->format->vsub, 1,
|
||||
&channel_1_plane);
|
||||
packed_pixels_addr_1x1(plane->frame_info,
|
||||
x_start / plane->frame_info->fb->format->hsub,
|
||||
y_start / plane->frame_info->fb->format->vsub, 2,
|
||||
packed_pixels_addr_1x1(&plane->frame_info,
|
||||
x_start / plane->frame_info.fb->format->hsub,
|
||||
y_start / plane->frame_info.fb->format->vsub, 2,
|
||||
&channel_2_plane);
|
||||
int step_y = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
int step_channel_1 = get_block_step_bytes(plane->frame_info->fb, direction, 1);
|
||||
int step_channel_2 = get_block_step_bytes(plane->frame_info->fb, direction, 2);
|
||||
int subsampling = get_subsampling(plane->frame_info->fb->format, direction);
|
||||
int step_y = get_block_step_bytes(plane->frame_info.fb, direction, 0);
|
||||
int step_channel_1 = get_block_step_bytes(plane->frame_info.fb, direction, 1);
|
||||
int step_channel_2 = get_block_step_bytes(plane->frame_info.fb, direction, 2);
|
||||
int subsampling = get_subsampling(plane->frame_info.fb->format, direction);
|
||||
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start);
|
||||
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,21 +55,11 @@ static struct drm_plane_state *
|
|||
vkms_plane_duplicate_state(struct drm_plane *plane)
|
||||
{
|
||||
struct vkms_plane_state *vkms_state;
|
||||
struct vkms_frame_info *frame_info;
|
||||
|
||||
vkms_state = kzalloc_obj(*vkms_state);
|
||||
if (!vkms_state)
|
||||
return NULL;
|
||||
|
||||
frame_info = kzalloc_obj(*frame_info);
|
||||
if (!frame_info) {
|
||||
DRM_DEBUG_KMS("Couldn't allocate frame_info\n");
|
||||
kfree(vkms_state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vkms_state->frame_info = frame_info;
|
||||
|
||||
__drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
|
||||
|
||||
return &vkms_state->base.base;
|
||||
|
|
@ -81,17 +71,14 @@ static void vkms_plane_destroy_state(struct drm_plane *plane,
|
|||
struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
|
||||
struct drm_crtc *crtc = vkms_state->base.base.crtc;
|
||||
|
||||
if (crtc && vkms_state->frame_info->fb) {
|
||||
if (crtc && vkms_state->frame_info.fb) {
|
||||
/* dropping the reference we acquired in
|
||||
* vkms_primary_plane_update()
|
||||
*/
|
||||
if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb))
|
||||
drm_framebuffer_put(vkms_state->frame_info->fb);
|
||||
if (drm_framebuffer_read_refcount(vkms_state->frame_info.fb))
|
||||
drm_framebuffer_put(vkms_state->frame_info.fb);
|
||||
}
|
||||
|
||||
kfree(vkms_state->frame_info);
|
||||
vkms_state->frame_info = NULL;
|
||||
|
||||
__drm_gem_destroy_shadow_plane_state(&vkms_state->base);
|
||||
kfree(vkms_state);
|
||||
}
|
||||
|
|
@ -143,7 +130,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
|
|||
vkms_plane_state = to_vkms_plane_state(new_state);
|
||||
shadow_plane_state = &vkms_plane_state->base;
|
||||
|
||||
frame_info = vkms_plane_state->frame_info;
|
||||
frame_info = &vkms_plane_state->frame_info;
|
||||
memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));
|
||||
memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));
|
||||
frame_info->fb = fb;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user