From nobody Sun Feb 8 13:59:05 2026 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 67FFD27F16C for ; Mon, 10 Nov 2025 15:46:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789585; cv=none; b=Bw9IPKIRSAnBUABp3sHkiZ32Zlf/kZNPk828UHwJa00c2TxeVcmBVVTLYX2x9z+oxsR8KDGbV+mZRKQb7T7K4ZtSOrbGKcORTF+Z5VLJejf0RIZblr0G5x+YzZNsd6Kh3NQnZJQ9UDa9Nk/fPq/f2b4ssOsGb/RQ+VIwoL/KapU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789585; c=relaxed/simple; bh=KKaGAq6XHKbbLckluYF/mU94P/+T+qTsJxd0ktgnxQA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dtUvOMWTufMPgiTc/gq4Qxd5v092xIQ3RlLL/6r0sETNQuK2iPxrr73apcLJbPXWPx6WynwEOKjmJm8l2yN0PcNtGDAUIOV1Rdn6OTmesUuKOv5kzpqv3iSELOkRnSVgl7SxirDbCr65M3utwn4OZV3DZ58NAGgQO3ajoDLfmZY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=YyTEkxPC; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=2BM3OD+z; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=YyTEkxPC; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=2BM3OD+z; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="YyTEkxPC"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="2BM3OD+z"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="YyTEkxPC"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="2BM3OD+z" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 5910833B2D; Mon, 10 Nov 2025 15:46:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fOMK+dNrkjOQwLiGVPFk8zzjI5swYYzDYeB+ANewajs=; b=YyTEkxPCpdYLg17i8OlrQCSwZybaqw9JrWZscLvd0icpbCbrWtEttDVTFym1VHp8239y6l 3/guHbTxmLL5LLGvnq5cO4T79lj3nvuSHECeJCc5vydr/6jl7RqIz63KBlezTnl4/nV+Lu DcbLtksP6CymzqSqNuodEJncye3MJ1s= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fOMK+dNrkjOQwLiGVPFk8zzjI5swYYzDYeB+ANewajs=; b=2BM3OD+zvL+vdENGCI0DJndEWLiPzRYyZpXLdxZz48lsPuhnravPPJWYCsxMCaY9lUJCJ4 GM7I6wqrQyyczjBg== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fOMK+dNrkjOQwLiGVPFk8zzjI5swYYzDYeB+ANewajs=; b=YyTEkxPCpdYLg17i8OlrQCSwZybaqw9JrWZscLvd0icpbCbrWtEttDVTFym1VHp8239y6l 3/guHbTxmLL5LLGvnq5cO4T79lj3nvuSHECeJCc5vydr/6jl7RqIz63KBlezTnl4/nV+Lu DcbLtksP6CymzqSqNuodEJncye3MJ1s= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fOMK+dNrkjOQwLiGVPFk8zzjI5swYYzDYeB+ANewajs=; b=2BM3OD+zvL+vdENGCI0DJndEWLiPzRYyZpXLdxZz48lsPuhnravPPJWYCsxMCaY9lUJCJ4 GM7I6wqrQyyczjBg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id EC89214485; Mon, 10 Nov 2025 15:46:20 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id OGZMOMwIEmlHXQAAD6G6ig (envelope-from ); Mon, 10 Nov 2025 15:46:20 +0000 From: Thomas Zimmermann To: jfalempe@redhat.com, javierm@redhat.com, francesco@valla.it, rrameshbabu@nvidia.com, simona@ffwll.ch, airlied@gmail.com, mripard@kernel.org, maarten.lankhorst@linux.intel.com, gregkh@linuxfoundation.org, jirislaby@kernel.org Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, Thomas Zimmermann Subject: [PATCH v2 1/3] drm/client: Pass force parameter to client restore Date: Mon, 10 Nov 2025 16:44:21 +0100 Message-ID: <20251110154616.539328-2-tzimmermann@suse.de> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251110154616.539328-1-tzimmermann@suse.de> References: <20251110154616.539328-1-tzimmermann@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Level: X-Spamd-Result: default: False [-6.80 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.de:email,suse.de:mid]; RCPT_COUNT_TWELVE(0.00)[14]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; FROM_HAS_DN(0.00)[]; FREEMAIL_TO(0.00)[redhat.com,valla.it,nvidia.com,ffwll.ch,gmail.com,kernel.org,linux.intel.com,linuxfoundation.org]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RLqirfcw6gnbcr9a9yhi49fhi6)]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO X-Spam-Score: -6.80 Content-Type: text/plain; charset="utf-8" Add force parameter to client restore and pass value through the layers. The only currently used value is false. If force is true, the client should restore its display even if it does not hold the DRM master lock. This is be required for emergency output, such as sysrq. While at it, inline drm_fb_helper_lastclose(), which is a trivial wrapper around drm_fb_helper_restore_fbdev_mode_unlocked(). Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe --- drivers/gpu/drm/clients/drm_fbdev_client.c | 6 ++++-- drivers/gpu/drm/drm_client_event.c | 4 ++-- drivers/gpu/drm/drm_fb_helper.c | 24 ++++++---------------- drivers/gpu/drm/drm_file.c | 2 +- include/drm/drm_client.h | 8 +++++--- include/drm/drm_client_event.h | 4 ++-- include/drm/drm_fb_helper.h | 8 ++------ 7 files changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/clients/drm_fbdev_client.c b/drivers/gpu/drm/c= lients/drm_fbdev_client.c index 47e5f27eee58..28951e392482 100644 --- a/drivers/gpu/drm/clients/drm_fbdev_client.c +++ b/drivers/gpu/drm/clients/drm_fbdev_client.c @@ -38,9 +38,11 @@ static void drm_fbdev_client_unregister(struct drm_clien= t_dev *client) } } =20 -static int drm_fbdev_client_restore(struct drm_client_dev *client) +static int drm_fbdev_client_restore(struct drm_client_dev *client, bool fo= rce) { - drm_fb_helper_lastclose(client->dev); + struct drm_fb_helper *fb_helper =3D drm_fb_helper_from_client(client); + + drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force); =20 return 0; } diff --git a/drivers/gpu/drm/drm_client_event.c b/drivers/gpu/drm/drm_clien= t_event.c index d25dc5250983..7b3e362f7926 100644 --- a/drivers/gpu/drm/drm_client_event.c +++ b/drivers/gpu/drm/drm_client_event.c @@ -102,7 +102,7 @@ void drm_client_dev_hotplug(struct drm_device *dev) } EXPORT_SYMBOL(drm_client_dev_hotplug); =20 -void drm_client_dev_restore(struct drm_device *dev) +void drm_client_dev_restore(struct drm_device *dev, bool force) { struct drm_client_dev *client; int ret; @@ -115,7 +115,7 @@ void drm_client_dev_restore(struct drm_device *dev) if (!client->funcs || !client->funcs->restore) continue; =20 - ret =3D client->funcs->restore(client); + ret =3D client->funcs->restore(client, force); drm_dbg_kms(dev, "%s: ret=3D%d\n", client->name, ret); if (!ret) /* The first one to return zero gets the privilege to restore = */ break; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helpe= r.c index 53e9dc0543de..1392738ce2fe 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -255,6 +255,7 @@ __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_= fb_helper *fb_helper, /** * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration * @fb_helper: driver-allocated fbdev helper, can be NULL + * @force: ignore present DRM master * * This helper should be called from fbdev emulation's &drm_client_funcs.r= estore * callback. It ensures that the user isn't greeted with a black screen wh= en the @@ -263,9 +264,9 @@ __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_= fb_helper *fb_helper, * Returns: * 0 on success, or a negative errno code otherwise. */ -int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_hel= per) +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_hel= per, bool force) { - return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, false); + return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force); } EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked); =20 @@ -1328,9 +1329,9 @@ int drm_fb_helper_set_par(struct fb_info *info) * the KDSET IOCTL with KD_TEXT, and only after that drops the master * status when exiting. * - * In the past this was caught by drm_fb_helper_lastclose(), but on - * modern systems where logind always keeps a drm fd open to orchestrate - * the vt switching, this doesn't work. + * In the past this was caught by drm_fb_helper_restore_fbdev_mode_unlock= ed(), + * but on modern systems where logind always keeps a drm fd open to + * orchestrate the vt switching, this doesn't work. * * To not break the userspace ABI we have this special case here, which * is only used for the above case. Everything else uses the normal @@ -1955,16 +1956,3 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper= *fb_helper) return 0; } EXPORT_SYMBOL(drm_fb_helper_hotplug_event); - -/** - * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulati= on - * @dev: DRM device - * - * This function is obsolete. Call drm_fb_helper_restore_fbdev_mode_unlock= ed() - * instead. - */ -void drm_fb_helper_lastclose(struct drm_device *dev) -{ - drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper); -} -EXPORT_SYMBOL(drm_fb_helper_lastclose); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index eebd1a05ee97..be5e617ceb9f 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -405,7 +405,7 @@ EXPORT_SYMBOL(drm_open); =20 static void drm_lastclose(struct drm_device *dev) { - drm_client_dev_restore(dev); + drm_client_dev_restore(dev, false); =20 if (dev_is_pci(dev->dev)) vga_switcheroo_process_delayed_switch(); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 5ecde0f6f591..c972a8a3385b 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -57,12 +57,14 @@ struct drm_client_funcs { * * Note that the core does not guarantee exclusion against concurrent * drm_open(). Clients need to ensure this themselves, for example by - * using drm_master_internal_acquire() and - * drm_master_internal_release(). + * using drm_master_internal_acquire() and drm_master_internal_release(). + * + * If the caller passes force, the client should ignore any present DRM + * master and restore the display anyway. * * This callback is optional. */ - int (*restore)(struct drm_client_dev *client); + int (*restore)(struct drm_client_dev *client, bool force); =20 /** * @hotplug: diff --git a/include/drm/drm_client_event.h b/include/drm/drm_client_event.h index 985d6f02a4c4..79369c755bc9 100644 --- a/include/drm/drm_client_event.h +++ b/include/drm/drm_client_event.h @@ -10,7 +10,7 @@ struct drm_device; #if defined(CONFIG_DRM_CLIENT) void drm_client_dev_unregister(struct drm_device *dev); void drm_client_dev_hotplug(struct drm_device *dev); -void drm_client_dev_restore(struct drm_device *dev); +void drm_client_dev_restore(struct drm_device *dev, bool force); void drm_client_dev_suspend(struct drm_device *dev); void drm_client_dev_resume(struct drm_device *dev); #else @@ -18,7 +18,7 @@ static inline void drm_client_dev_unregister(struct drm_d= evice *dev) { } static inline void drm_client_dev_hotplug(struct drm_device *dev) { } -static inline void drm_client_dev_restore(struct drm_device *dev) +static inline void drm_client_dev_restore(struct drm_device *dev, bool for= ce) { } static inline void drm_client_dev_suspend(struct drm_device *dev) { } diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index c1d38d54a112..63e3af8dd5ed 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -254,7 +254,8 @@ int drm_fb_helper_set_par(struct fb_info *info); int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info); =20 -int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_hel= per); +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_hel= per, + bool force); =20 struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper); void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper); @@ -283,7 +284,6 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *f= b_helper); int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); int drm_fb_helper_debug_enter(struct fb_info *info); int drm_fb_helper_debug_leave(struct fb_info *info); -void drm_fb_helper_lastclose(struct drm_device *dev); #else static inline void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, @@ -409,10 +409,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_= info *info) { return 0; } - -static inline void drm_fb_helper_lastclose(struct drm_device *dev) -{ -} #endif =20 #endif --=20 2.51.1 From nobody Sun Feb 8 13:59:05 2026 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B94BF2749D2 for ; Mon, 10 Nov 2025 15:46:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789591; cv=none; b=eH1craSr9Fx719RZnJ9HyGwaWBGEfA0paTh9MfU6sxzZ6JRvZNkkPqI46SLTs90Tz+Y/4fWoLdrD0liUfl2raaPb6/dWIrJXYZoLiZkGvK56az13UiBOvkXSE6PjKlvCyZ3sAQrxzQ7R7txBTNdc08tfQT/+/6bvyOE8i+2YYgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789591; c=relaxed/simple; bh=q46jkVHpjThdcdIlC6rv7wu6lZAcE9xd+RpQXcXB704=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rFlU/t3NIG3sIMLK9/EmvoOhK+rrO4jy10JxyCbvfFJkF8L8NxAacYVHFBvmOF4ePxCFLwWjGTIHKuGEnWE1hyZLoUlbsMtvm6tQ+H2IaFezf6HRTkoaVOqETlAhLptyQKJHdvkxhGcTCeCyfAzsv2SJ/AJTL9hovNRrU/y1E04= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=mGV9mSc4; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=QINbr+8U; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=mGV9mSc4; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=QINbr+8U; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="mGV9mSc4"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="QINbr+8U"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="mGV9mSc4"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="QINbr+8U" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id C1F002049E; Mon, 10 Nov 2025 15:46:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lU9WwAjaEFXWGP8ujUJjp7R24LRStD9xFc60d0DDK4Q=; b=mGV9mSc43X6kqETu1VxFya/5Ilhu3Hi4JbkeKTJUNDUmlK4c5UWDhYIxHkI41RQgE/vdAn phnSG5k1yALb+fq9KMBwI9yPPea7JjWL5Gc8oO+A6Xv+gCHQ8OPGNYhy9w4ANb9/235+zS 2HVkWGCy8LmWolJlpbb/8nq2oeqB54c= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lU9WwAjaEFXWGP8ujUJjp7R24LRStD9xFc60d0DDK4Q=; b=QINbr+8U0nx9y8dbZ8TTbhu1USFVzgNV2GN3JjmoMn5mnLRdZrNwGwQh8Ty4SbsbXJzhvj 36qERfzIs0PzLZAA== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lU9WwAjaEFXWGP8ujUJjp7R24LRStD9xFc60d0DDK4Q=; b=mGV9mSc43X6kqETu1VxFya/5Ilhu3Hi4JbkeKTJUNDUmlK4c5UWDhYIxHkI41RQgE/vdAn phnSG5k1yALb+fq9KMBwI9yPPea7JjWL5Gc8oO+A6Xv+gCHQ8OPGNYhy9w4ANb9/235+zS 2HVkWGCy8LmWolJlpbb/8nq2oeqB54c= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1762789581; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lU9WwAjaEFXWGP8ujUJjp7R24LRStD9xFc60d0DDK4Q=; b=QINbr+8U0nx9y8dbZ8TTbhu1USFVzgNV2GN3JjmoMn5mnLRdZrNwGwQh8Ty4SbsbXJzhvj 36qERfzIs0PzLZAA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 5FE9D14483; Mon, 10 Nov 2025 15:46:21 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id UFs0Fs0IEmlHXQAAD6G6ig (envelope-from ); Mon, 10 Nov 2025 15:46:21 +0000 From: Thomas Zimmermann To: jfalempe@redhat.com, javierm@redhat.com, francesco@valla.it, rrameshbabu@nvidia.com, simona@ffwll.ch, airlied@gmail.com, mripard@kernel.org, maarten.lankhorst@linux.intel.com, gregkh@linuxfoundation.org, jirislaby@kernel.org Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, Thomas Zimmermann Subject: [PATCH v2 2/3] drm/client: Support emergency restore via sysrq for all clients Date: Mon, 10 Nov 2025 16:44:22 +0100 Message-ID: <20251110154616.539328-3-tzimmermann@suse.de> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251110154616.539328-1-tzimmermann@suse.de> References: <20251110154616.539328-1-tzimmermann@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spamd-Result: default: False [-6.80 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email,imap1.dmz-prg2.suse.org:helo]; RCPT_COUNT_TWELVE(0.00)[14]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; FROM_HAS_DN(0.00)[]; FREEMAIL_TO(0.00)[redhat.com,valla.it,nvidia.com,ffwll.ch,gmail.com,kernel.org,linux.intel.com,linuxfoundation.org]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RLqirfcw6gnbcr9a9yhi49fhi6)]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO X-Spam-Score: -6.80 X-Spam-Level: Content-Type: text/plain; charset="utf-8" Move the sysrq functionality from DRM fbdev helpers to the DRM device and in-kernel clients, so that it becomes available on all clients. DRM fbdev helpers support emergency restoration of the console output via a special key combination. Press SysRq+v to replace the current compositor with the kernel's output on the framebuffer console. This allows users to see the log messages during system emergencies. By moving the functionality from fbdev helpers to the DRM device, any in-kernel client can serve as emergency output. This can be used to bring up drm_log, for example. Each DRM device registers itself to the list of possible sysrq handlers. On receiving SysRq+v, the DRM core goes over all registered devices and restores an in-kernel DRM client for each of them. See Documentation/admin-guide/sysrq.rst on how to invoke SysRq. Switch VTs to bring back the user-space compositor. v2: - declare placeholders as 'static inline' (kernel test robot) - fix grammar in commit description Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe --- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_client.c | 1 + drivers/gpu/drm/drm_client_sysrq.c | 65 ++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_drv.c | 3 ++ drivers/gpu/drm/drm_fb_helper.c | 45 +-------------------- drivers/gpu/drm/drm_internal.h | 11 +++++ include/drm/drm_device.h | 8 ++++ 7 files changed, 91 insertions(+), 45 deletions(-) create mode 100644 drivers/gpu/drm/drm_client_sysrq.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 7789f42027ff..33ff76ae52b2 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -76,7 +76,8 @@ drm-y :=3D \ drm-$(CONFIG_DRM_CLIENT) +=3D \ drm_client.o \ drm_client_event.o \ - drm_client_modeset.o + drm_client_modeset.o \ + drm_client_sysrq.o drm-$(CONFIG_DRM_LIB_RANDOM) +=3D lib/drm_random.o drm-$(CONFIG_COMPAT) +=3D drm_ioc32.o drm-$(CONFIG_DRM_PANEL) +=3D drm_panel.o diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 504ec5bdfa2c..a82d741e6630 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -11,6 +11,7 @@ #include =20 #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_client_sysrq.c b/drivers/gpu/drm/drm_clien= t_sysrq.c new file mode 100644 index 000000000000..eea660096f1b --- /dev/null +++ b/drivers/gpu/drm/drm_client_sysrq.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT + +#include + +#include +#include +#include + +#include "drm_internal.h" + +#ifdef CONFIG_MAGIC_SYSRQ +static LIST_HEAD(drm_client_sysrq_dev_list); +static DEFINE_MUTEX(drm_client_sysrq_dev_lock); + +/* emergency restore, don't bother with error reporting */ +static void drm_client_sysrq_restore_work_fn(struct work_struct *ignored) +{ + struct drm_device *dev; + + guard(mutex)(&drm_client_sysrq_dev_lock); + + list_for_each_entry(dev, &drm_client_sysrq_dev_list, client_sysrq_list) { + if (dev->switch_power_state =3D=3D DRM_SWITCH_POWER_OFF) + continue; + + drm_client_dev_restore(dev, true); + } +} + +static DECLARE_WORK(drm_client_sysrq_restore_work, drm_client_sysrq_restor= e_work_fn); + +static void drm_client_sysrq_restore_handler(u8 ignored) +{ + schedule_work(&drm_client_sysrq_restore_work); +} + +static const struct sysrq_key_op drm_client_sysrq_restore_op =3D { + .handler =3D drm_client_sysrq_restore_handler, + .help_msg =3D "force-fb(v)", + .action_msg =3D "Restore framebuffer console", +}; + +void drm_client_sysrq_register(struct drm_device *dev) +{ + guard(mutex)(&drm_client_sysrq_dev_lock); + + if (list_empty(&drm_client_sysrq_dev_list)) + register_sysrq_key('v', &drm_client_sysrq_restore_op); + + list_add(&dev->client_sysrq_list, &drm_client_sysrq_dev_list); +} + +void drm_client_sysrq_unregister(struct drm_device *dev) +{ + guard(mutex)(&drm_client_sysrq_dev_lock); + + /* remove device from global restore list */ + if (!drm_WARN_ON(dev, list_empty(&dev->client_sysrq_list))) + list_del(&dev->client_sysrq_list); + + /* no devices left; unregister key */ + if (list_empty(&drm_client_sysrq_dev_list)) + unregister_sysrq_key('v', &drm_client_sysrq_restore_op); +} +#endif diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8e3cb08241c8..2915118436ce 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -733,6 +733,7 @@ static int drm_dev_init(struct drm_device *dev, INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->filelist_internal); INIT_LIST_HEAD(&dev->clientlist); + INIT_LIST_HEAD(&dev->client_sysrq_list); INIT_LIST_HEAD(&dev->vblank_event_list); =20 spin_lock_init(&dev->event_lock); @@ -1100,6 +1101,7 @@ int drm_dev_register(struct drm_device *dev, unsigned= long flags) goto err_unload; } drm_panic_register(dev); + drm_client_sysrq_register(dev); =20 DRM_INFO("Initialized %s %d.%d.%d for %s on minor %d\n", driver->name, driver->major, driver->minor, @@ -1144,6 +1146,7 @@ void drm_dev_unregister(struct drm_device *dev) { dev->registered =3D false; =20 + drm_client_sysrq_unregister(dev); drm_panic_unregister(dev); =20 drm_client_dev_unregister(dev); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helpe= r.c index 1392738ce2fe..9a734017756b 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -32,7 +32,6 @@ #include #include #include -#include #include =20 #include @@ -270,42 +269,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct d= rm_fb_helper *fb_helper, b } EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked); =20 -#ifdef CONFIG_MAGIC_SYSRQ -/* emergency restore, don't bother with error reporting */ -static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) -{ - struct drm_fb_helper *helper; - - mutex_lock(&kernel_fb_helper_lock); - list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { - struct drm_device *dev =3D helper->dev; - - if (dev->switch_power_state =3D=3D DRM_SWITCH_POWER_OFF) - continue; - - mutex_lock(&helper->lock); - drm_client_modeset_commit_locked(&helper->client); - mutex_unlock(&helper->lock); - } - mutex_unlock(&kernel_fb_helper_lock); -} - -static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work= _fn); - -static void drm_fb_helper_sysrq(u8 dummy1) -{ - schedule_work(&drm_fb_helper_restore_work); -} - -static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op =3D { - .handler =3D drm_fb_helper_sysrq, - .help_msg =3D "force-fb(v)", - .action_msg =3D "Restore framebuffer console", -}; -#else -static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op =3D { }; -#endif - static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) { struct drm_fb_helper *fb_helper =3D info->par; @@ -602,11 +565,8 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helpe= r) drm_fb_helper_release_info(fb_helper); =20 mutex_lock(&kernel_fb_helper_lock); - if (!list_empty(&fb_helper->kernel_fb_list)) { + if (!list_empty(&fb_helper->kernel_fb_list)) list_del(&fb_helper->kernel_fb_list); - if (list_empty(&kernel_fb_helper_list)) - unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - } mutex_unlock(&kernel_fb_helper_lock); =20 if (!fb_helper->client.funcs) @@ -1840,9 +1800,6 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_= fb_helper *fb_helper) info->node, info->fix.id); =20 mutex_lock(&kernel_fb_helper_lock); - if (list_empty(&kernel_fb_helper_list)) - register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); mutex_unlock(&kernel_fb_helper_lock); =20 diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 5a3bed48ab1f..f893b1e3a596 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -56,6 +56,17 @@ static inline void drm_client_debugfs_init(struct drm_de= vice *dev) { } #endif =20 +/* drm_client_sysrq.c */ +#if defined(CONFIG_DRM_CLIENT) && defined(CONFIG_MAGIC_SYSRQ) +void drm_client_sysrq_register(struct drm_device *dev); +void drm_client_sysrq_unregister(struct drm_device *dev); +#else +static inline void drm_client_sysrq_register(struct drm_device *dev) +{ } +static inline void drm_client_sysrq_unregister(struct drm_device *dev) +{ } +#endif + /* drm_file.c */ extern struct mutex drm_global_mutex; bool drm_dev_needs_global_mutex(struct drm_device *dev); diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 778b2cca6c49..5af49c5c3778 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -238,6 +238,14 @@ struct drm_device { */ struct list_head clientlist; =20 + /** + * @client_sysrq_list: + * + * Entry into list of devices registered for sysrq. Allows in-kernel + * clients on this device to handle sysrq keys. + */ + struct list_head client_sysrq_list; + /** * @vblank_disable_immediate: * --=20 2.51.1 From nobody Sun Feb 8 13:59:05 2026 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B171628466F for ; Mon, 10 Nov 2025 15:46:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789598; cv=none; b=WXlSpslYG1kUljjD3SmjQ+hY5/MNxOL08MuHh/UzIvIyRxk4M/wqfSOqaAef7slS0sh+A5zsybywevmWO5rfEm3bcNtgATdlzdT0Xf/YmouKZOgAN5pGfMGgzKnsy+v6PKw2FcZsINbjonqYBCP2H/gmo2cc9KRvGbQTWuRbnDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762789598; c=relaxed/simple; bh=dM9bmM9py3GYfWcHuKRXV4WzQoK5kgYEqjdYxCIYtcU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y1Fz9UZIMzrkREG0OFhmlGE7/M8aw+r5/nGJzad6ZIPV7/53ZYv8lLUzY+4Z94fyCfTwLtmYtqt+lfsR2Aa3doev8NVys1NUpRCcrwYbtd4SuqXGhSeEv1lia1UNH0yb4TMMbbiC4gIt8CpVS6xWkckfG4io18AKbLyMkfxQ5Sc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 431BF204AB; Mon, 10 Nov 2025 15:46:22 +0000 (UTC) Authentication-Results: smtp-out2.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id CA51B14485; Mon, 10 Nov 2025 15:46:21 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id aKbzL80IEmlHXQAAD6G6ig (envelope-from ); Mon, 10 Nov 2025 15:46:21 +0000 From: Thomas Zimmermann To: jfalempe@redhat.com, javierm@redhat.com, francesco@valla.it, rrameshbabu@nvidia.com, simona@ffwll.ch, airlied@gmail.com, mripard@kernel.org, maarten.lankhorst@linux.intel.com, gregkh@linuxfoundation.org, jirislaby@kernel.org Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, Thomas Zimmermann Subject: [PATCH v2 3/3] drm/client: log: Implement struct drm_client_funcs.restore Date: Mon, 10 Nov 2025 16:44:23 +0100 Message-ID: <20251110154616.539328-4-tzimmermann@suse.de> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251110154616.539328-1-tzimmermann@suse.de> References: <20251110154616.539328-1-tzimmermann@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Queue-Id: 431BF204AB X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Spam-Flag: NO X-Spam-Score: -4.00 X-Spam-Level: X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[] Content-Type: text/plain; charset="utf-8" Restore the log client's output when the DRM core invokes the restore callback. Follow the existing behavior of fbdev emulation wrt. the value of the force parameter. If force is false, acquire the DRM master lock and reprogram the display. This is the case when the user-space compositor exits and the DRM core transfers the display back to the in-kernel client. This also enables drm_log output during reboot and shutdown. If force is true, reprogram without considering the master lock. This overrides the current compositor and prints the log to the screen. In case of system malfunction, users can enter SysRq+v to invoke the emergency error reporting. See Documentation/admin-guide/sysrq.rst for more information. v2: - s/exists/exits/ in second paragraph of commit description - fix grammar in commit description Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe --- drivers/gpu/drm/clients/drm_log.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/clients/dr= m_log.c index 19e55aa0ed74..4d3005273b27 100644 --- a/drivers/gpu/drm/clients/drm_log.c +++ b/drivers/gpu/drm/clients/drm_log.c @@ -315,6 +315,18 @@ static void drm_log_client_unregister(struct drm_clien= t_dev *client) drm_client_release(client); } =20 +static int drm_log_client_restore(struct drm_client_dev *client, bool forc= e) +{ + int ret; + + if (force) + ret =3D drm_client_modeset_commit_locked(client); + else + ret =3D drm_client_modeset_commit(client); + + return ret; +} + static int drm_log_client_hotplug(struct drm_client_dev *client) { struct drm_log *dlog =3D client_to_drm_log(client); @@ -348,6 +360,7 @@ static const struct drm_client_funcs drm_log_client_fun= cs =3D { .owner =3D THIS_MODULE, .free =3D drm_log_client_free, .unregister =3D drm_log_client_unregister, + .restore =3D drm_log_client_restore, .hotplug =3D drm_log_client_hotplug, .suspend =3D drm_log_client_suspend, .resume =3D drm_log_client_resume, --=20 2.51.1