From nobody Sat Jun 20 11:49:36 2026 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (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 98D2139099A for ; Wed, 15 Apr 2026 17:40:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274842; cv=none; b=OW56p8dWzo1IoowdidzMuJIopVb18FGYAV95kGFkw0wB7HdHxEk5YgyGykGqosQcrFB75SIv5bFwQsw+AySAjEPC9jDxKT0eolLk80HGKYz/YBSaiZCdRY9j5IPW+FH5eYXeVD8HN+zuf2GMgOIGysbjzv2xQRE8EJAwRRgoVew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274842; c=relaxed/simple; bh=+pHt1PdX1ZX2M9ksmMWjbdl6LSzaUGO1nZKoaNMIRv4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=m7PMB2fvi7Vxjye8XfnI2X0UgesZebKPpy06aJ05k9nIjwZMPOXVPyhUPbV+qHCbRPQ0SFm9IwUDqa+pgS4shJdikFFUYXrGyH9XetpmU2/+iHH+ZSt7galP02I2O8yTsCnrkoUwgxhRXX0n1kzb3EOBAUNLMgCOVlVzOQ9NhRw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eEY372HJ; arc=none smtp.client-ip=209.85.216.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eEY372HJ" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-35e576110adso2598690a91.0 for ; Wed, 15 Apr 2026 10:40:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776274841; x=1776879641; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qk8GKpbjud7iZDAxYS6mtLV1J/SUvTNFEIEfpQruf8s=; b=eEY372HJdQdUCYXg9m1mpMmTzulu43dOgQzV8Dn2Njp0YffsjpZRuQM98tD7JXqytX 4ddHjzsfUef2gXnDEpqHNZBhf+cTWCCjYe+5h5zPaGZ0oRAwnEMfq6JFLtUYaNeBEnur c1wJ5jpDTObRTul0g5Le/oSoimhEwUL+9VbCM6kIrLz5l6AA/9UZaTOCtxFsTUIGr5xr DlPFyF3VaKbwbt9MBHWZZVFBily0n/TxXb0pYRHVNApNCGQxrOiM8NJ5F9jaEWpwfF6l bBFE6jD52KL4WcMcL+ausMXiHBEE4RucE9hMYOzg+1eKDycyuxT8LCmgThoSv7Bp4nz3 d1Iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776274841; x=1776879641; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qk8GKpbjud7iZDAxYS6mtLV1J/SUvTNFEIEfpQruf8s=; b=f+lXTv64r1yPcc+j1uBSws+mRrRzNkRgxExZs5au87ipgaftWVH/b09gK/c7dB3m/u aHKEY3RPKZ5g4/3vQdi7yP6C3ijqrWXmMqyxCj3SixAPoXkiXPfz+SOv7HmlzOzFWjDS I0dYIQisR9Gd2+gLd0zxub9C/5mRlTK6NUF0Obx5cTT4383kvmawxMsiptFkie992uJx LBPGvqkfRk3pZCOdo4I5wUFL8V8fKxkEmGqu4vohenBlV/9HklapQPLsYr1Cf3JlQ4uj QhMXVWRmY7UA6qpvCtH5cd3Vpg6cVV1DEh6xfvk/B1nY5qEcK1dPaK5z/dnuhuwNU6co AGLw== X-Forwarded-Encrypted: i=1; AFNElJ9zfWhBHYJlGlsjQuJA3CEp6wEO6HOsFUE21SbTO/PRxDST8JhwL1wZyP48BtV/VHok0eAO49ebrIbhXL0=@vger.kernel.org X-Gm-Message-State: AOJu0Yw2mt519hZgo+4SbHdnZzt/E+DErB8/OTJiA2QGcBiyZnKYw0xE ZT7YZKAEday78/VB5jX0b4d1c63uD10b5oMfLX3EgFtouUbS9s0gzx2l X-Gm-Gg: AeBDievMtWy11XVk7VpdFQit0pf8hBJtmTBKB3XC6Nr0lenPn2oX2xbyeZvmmSm86wJ yXMBbc720s/lejV4kJBzglZQqVcT+ZtuYE2PW9hsM980Gra1hB/KB89yo9r5yWvJptrNAwnSj/z yDLvf0KjuRaC4TwmIPYKfa6FbG+dC1BX9MskLRBdNPqI2V90SdfcbIvQe3wASksMhaCOdEgdpLm HrHXBPfD/XQVwGhyvZoplgddHUfPyiru9+YuCiOU2CUxFvB708beK2e25rNb0THzYMg5xo4deFh adXFN9DxKeqvbgpmzhwfzBMccrwqTXQzM2riuKRB2wtQXPC4u3NW9k9PJsRxV/usJeoaKb8IpQK ZRCd6T6dgbkYK5BE4G3wFUkWugGZ+H5CUw82HRs7V2zYrF1B7lC0uAwqKBaxYPV2xwJHvaAIisZ onoFyCb3sEynUjPEpv2nfUX50Yo4LNiy9ZhYF1euyGCAWYvLQv+tPo8bxVW+2B7LpkQxE0JYOgE BpiNhkWEig69VuIZGr/MoxLO4EStKB6xLNC7Q== X-Received: by 2002:a17:90b:4e86:b0:35b:952c:43ab with SMTP id 98e67ed59e1d1-3612f2ab68cmr375051a91.4.1776274840928; Wed, 15 Apr 2026 10:40:40 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35fd1fe9b50sm2891026a91.3.2026.04.15.10.40.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 10:40:40 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v1 1/4] virtio: separate PM restore and reset_done paths Date: Thu, 16 Apr 2026 02:38:30 +0900 Message-Id: <20260415173833.6319-2-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415173833.6319-1-baver.bae@gmail.com> References: <20260415173833.6319-1-baver.bae@gmail.com> 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 Content-Type: text/plain; charset="utf-8" From: Sungho Bae Refactor virtio_device_restore_priv() by extracting the common device re-initialization sequence into virtio_device_reinit(). This helper performs the full bring-up sequence: reset, status acknowledgment, feature finalization, and feature negotiation. virtio_device_restore() and virtio_device_reset_done() now each call virtio_device_reinit() directly instead of going through a boolean- dispatched wrapper. This makes each path independently readable and extensible without further complicating the dispatch logic. A follow-up series will add noirq PM callbacks that only affect the restore path; having the two paths separated avoids adding more conditionals to a shared function. No functional change. Signed-off-by: Sungho Bae --- drivers/virtio/virtio.c | 78 +++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 5bdc6b82b30b..b0668434ac21 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -588,7 +588,7 @@ void unregister_virtio_device(struct virtio_device *dev) } EXPORT_SYMBOL_GPL(unregister_virtio_device); =20 -static int virtio_device_restore_priv(struct virtio_device *dev, bool rest= ore) +static int virtio_device_reinit(struct virtio_device *dev) { struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); int ret; @@ -613,35 +613,9 @@ static int virtio_device_restore_priv(struct virtio_de= vice *dev, bool restore) =20 ret =3D dev->config->finalize_features(dev); if (ret) - goto err; - - ret =3D virtio_features_ok(dev); - if (ret) - goto err; - - if (restore) { - if (drv->restore) { - ret =3D drv->restore(dev); - if (ret) - goto err; - } - } else { - ret =3D drv->reset_done(dev); - if (ret) - goto err; - } - - /* If restore didn't do it, mark device DRIVER_OK ourselves. */ - if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) - virtio_device_ready(dev); - - virtio_config_core_enable(dev); - - return 0; + return ret; =20 -err: - virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); - return ret; + return virtio_features_ok(dev); } =20 #ifdef CONFIG_PM_SLEEP @@ -668,7 +642,30 @@ EXPORT_SYMBOL_GPL(virtio_device_freeze); =20 int virtio_device_restore(struct virtio_device *dev) { - return virtio_device_restore_priv(dev, true); + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + + if (drv && drv->restore) { + ret =3D drv->restore(dev); + if (ret) + goto err; + } + + /* If restore didn't do it, mark device DRIVER_OK ourselves. */ + if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) + virtio_device_ready(dev); + + virtio_config_core_enable(dev); + + return 0; + +err: + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); + return ret; } EXPORT_SYMBOL_GPL(virtio_device_restore); #endif @@ -698,11 +695,30 @@ EXPORT_SYMBOL_GPL(virtio_device_reset_prepare); int virtio_device_reset_done(struct virtio_device *dev) { struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; =20 if (!drv || !drv->reset_done) return -EOPNOTSUPP; =20 - return virtio_device_restore_priv(dev, false); + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + + ret =3D drv->reset_done(dev); + if (ret) + goto err; + + /* If reset_done didn't do it, mark device DRIVER_OK ourselves. */ + if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) + virtio_device_ready(dev); + + virtio_config_core_enable(dev); + + return 0; + +err: + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); + return ret; } EXPORT_SYMBOL_GPL(virtio_device_reset_done); =20 --=20 2.34.1 From nobody Sat Jun 20 11:49:36 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (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 26E343EBF0C for ; Wed, 15 Apr 2026 17:40:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274845; cv=none; b=aAhSX2VKAH4rOEI/YcM5wDT2vNvu319z4+2y+l5fGLlu1/LywzKb3VWGYtKa5j1Jpsji8XY6oARIO4UXRHQ62N8MjwWTc4B3/CXzi5alvKOdGQHNNRwfWcCGp1lKGe0bG/jj5aHPCIOf0vnsBi3fKRX4QEJkXlm3Ks7IzhcHNCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274845; c=relaxed/simple; bh=/wzY0uR7XsAJFVFm2VHFAgX1e1WWVRZFNs7XSXLzWTE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CObyNutqEHGm18tU7rPRIVwT0Kt4Xoy9sMITdb8P9JWUILqiRVonk3O4JiyMhbWHrUv5E1bhS+Ak7lY+RX/QYl3qPEuAYJzy4qzciUc0QudfaoxQ+bYKCEP9AiMu8AyN9sCuQXW8ZtLQgFjLBqJw9xgV7lh9VZvPdwwBQYdYOFI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PuSc8wXR; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PuSc8wXR" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-35691a231a7so4534604a91.3 for ; Wed, 15 Apr 2026 10:40:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776274843; x=1776879643; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=s02OsJTTkDH9VQI7tIvBGr+0nakaQaimTmuWsyQJa9E=; b=PuSc8wXRvVPfmY1jKjOFVuziOeFA/iK/Ynrunf2dws2CemBpH6p91VsdcTdq0jTnjO ENsGoIIkMJsL0XM53SiESU5bxyb+kjoF+Hxj/jAPAUxYhiVWn37TnifyTJdb1PrVIisJ bIuQW7H5K/iiR7addd5NbYwT83e5PHXKjp7U0oWuaeiij3qmHKDwChK3EW80vA24GauX BhP6NiszgrvXbNHnZ4OCrcDzhGyfSefP8G1C5ZTSTmNhG5G0ewlOsWHzR7aro2jeVC01 8LizG8ijqtUq7ZUAFCbdBNKCtA28ZKNZ1f8GcHQuXGJRsS/NOnD2ghs102anFrWmGsVf mQFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776274843; x=1776879643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=s02OsJTTkDH9VQI7tIvBGr+0nakaQaimTmuWsyQJa9E=; b=MSArID38cWO41PW7gqLLqbc+gHZNSUafwR7gtj9Lk3Aa/wz7JuRz9EWsDCS8lQVTob BtjCm2Sf7n7qVguXI/Nv3VBFgIwBTAW4ESo6jDmARxd+Tr5sFvZyFMErnYuGt0HQ2dZ2 fdAw1YjeLQFpkui4m8dYsR8GZw7WO1yrG9gzFJROEB+dG2fESbsrFHQAfBtYv6KSK7X+ VOObnK5OqHLSlQ34YCYJPngsyFL4Se0BLuMmhipJA3D4o2b+3nHFCs1awvWQxfROkPW1 G0REIlL9yaA1XgQQBHAhRWFoSIOFW19svizLuzBXDF5s4F0xzYgosbhFkvg2Gj0+T3vr W1Sw== X-Forwarded-Encrypted: i=1; AFNElJ+lZ89tWoVOkT6aca1sEcnppomuVzyGVJT0gBx44x2V+aU6wVHPc4pB5EyqeU9iNfUDiRmUFGUeun2K9aE=@vger.kernel.org X-Gm-Message-State: AOJu0YzfwyPCLy6j5lKEknTdnfUsYGESM58jSXxt2RgGOqni6GYtB1du Nyyra/gwmVBw9V6j/snFmJpJj2/rC1zpz6KO+7Wj/k9VW7yRw3rUoGkoeW0I6UrY X-Gm-Gg: AeBDievt47i9iukHByjICRC142pKaBGghWke/1gXPIipOP9xJXNrU0qSxcj80KhbC+z ki/ageVOYfdAjWLOCftH1a3c+khGKk88HyE4lAyA4STHz0mGftatpu9NY3UgeXYEbTTYvRbtTa7 WQ9UFC4n01CKzpUkb4WXYwjSphvRvPFDz2DeLYsPgD3j0hUOG4Jdt7rfd68+fdkxzTy2yJrLrBK UqJVfXJWJ1nPI2Riky+xO1nDrwFj0nw3DPl8hFqbMLqw62xuSUZlmseiqvCGohE7jgoVyNkTHDH ac8qzjUUZw76EabP8x/W4Robzsfib6Zu0Ag7yZVMBDIJcn36W/heb3wligiHrCBbZ5Al8yQThFa UdUhpXftQIaehAok0pTv0HNrS2Be38++tqnz4UPFbo3HrTZe0t8Csc+DWX7mIMGSZDPRzXhA+I9 oX4vxtVMp75qWbcDexqHZA1dtVTZ9bMBwdSoR9LFAHCDbW2h+xqcR6KAxYWotA3NaOoMLhu2sUs rk66j4VVxB66aJSYCHZY4+OzytSTf4/jUHRyw== X-Received: by 2002:a17:90b:4d0e:b0:35c:b02:b5c1 with SMTP id 98e67ed59e1d1-35e4254fa24mr22085159a91.2.1776274843412; Wed, 15 Apr 2026 10:40:43 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35fd1fe9b50sm2891026a91.3.2026.04.15.10.40.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 10:40:43 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v1 2/4] virtio_ring: export virtqueue_reinit_vring() for noirq restore Date: Thu, 16 Apr 2026 02:38:31 +0900 Message-Id: <20260415173833.6319-3-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415173833.6319-1-baver.bae@gmail.com> References: <20260415173833.6319-1-baver.bae@gmail.com> 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 Content-Type: text/plain; charset="utf-8" From: Sungho Bae After a device reset in noirq context the existing vrings must be re-initialized without any memory allocation, because GFP_KERNEL is not available. The internal helpers virtqueue_reset_split() and virtqueue_reset_packed() already reset vring indices and descriptor state in place. Add a thin exported wrapper, virtqueue_reinit_vring(), that dispatches to the appropriate helper based on the ring layout. This will be used by a subsequent patch that adds noirq system-sleep PM callbacks for virtio-mmio. Signed-off-by: Sungho Bae --- drivers/virtio/virtio_ring.c | 19 +++++++++++++++++++ include/linux/virtio_ring.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index fbca7ce1c6bf..a57c625b5936 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -3936,5 +3936,24 @@ void virtqueue_map_sync_single_range_for_device(cons= t struct virtqueue *_vq, } EXPORT_SYMBOL_GPL(virtqueue_map_sync_single_range_for_device); =20 +/** + * virtqueue_reinit_vring - reinitialize vring state without reallocation + * @_vq: the virtqueue + * + * Reset the avail/used indices and descriptor state of an existing + * virtqueue so it can be reused after a device reset. No memory is + * allocated or freed, making this safe for use in noirq context. + */ +void virtqueue_reinit_vring(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq =3D to_vvq(_vq); + + if (virtqueue_is_packed(vq)) + virtqueue_reset_packed(vq); + else + virtqueue_reset_split(vq); +} +EXPORT_SYMBOL_GPL(virtqueue_reinit_vring); + MODULE_DESCRIPTION("Virtio ring implementation"); MODULE_LICENSE("GPL"); diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index c97a12c1cda3..26c7c9d0a151 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -118,6 +118,9 @@ void vring_del_virtqueue(struct virtqueue *vq); /* Filter out transport-specific feature bits. */ void vring_transport_features(struct virtio_device *vdev); =20 +/* Reinitialize a virtqueue without reallocation (safe in noirq context) */ +void virtqueue_reinit_vring(struct virtqueue *_vq); + irqreturn_t vring_interrupt(int irq, void *_vq); =20 u32 vring_notification_data(struct virtqueue *_vq); --=20 2.34.1 From nobody Sat Jun 20 11:49:36 2026 Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) (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 D811D3ED119 for ; Wed, 15 Apr 2026 17:40:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274848; cv=none; b=CRzso+vMUWi+PYOU7JirC79XX0diMBGCoSe+vxz0LQINoW2Vu+T7qJIcl+kPIaR6dFoXerPrt/J1cV1WPEawZmVLiWT+nJ/ysWWurMd9JRHVq8Y2j+GHJgQJr9d+NLU7cXP7hNpc/usrhwdSPn+X0UNfO9bmSDjffiPzi+NX83w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274848; c=relaxed/simple; bh=oUKWHuNZaoLE+BCBO8pAW4ajUqCywpdJbJc4MQ3GnHc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZHEjlK4HKdQkEGNc+/vF7Tl1M/XPzBc0SrrNOAOZ8Sy1to3U3z5vOZw+wlmNod+hsm7hrD+Rw1J2jhkK1rDJcymlQvLieha8lihfP3z4Rl1aDqAlPyjnoNrQAs7lPajy/9C+jGILPqp7HGghUDMfQaat5VRO6xXBKAl2m5YKtMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Gyes52gm; arc=none smtp.client-ip=209.85.216.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Gyes52gm" Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-35fb166b0c6so1857340a91.0 for ; Wed, 15 Apr 2026 10:40:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776274846; x=1776879646; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1mmHtcDWBE7cV3MaI0SOK53oi2aQIxBNXcDXsA8cCN0=; b=Gyes52gmBE7Rx0kDfGhWwWHGX8fF5mAOJCQuX4d0ZK4Dohyiy+R4MZ67CF2Q3bvO4e 2EBBlYKCAtTY2lSnjxdsaX5DPElKGBlor//DyjH8oGAq/0d9660crH53G6wpxl/kxi9F aZPlMxykaGcSK9zWXnIosxVzcfEy1Gbz3UKRxH/oyUcTyKArQBso/mIrkABD4lDq84EP M4W0wbhNUfmYPW/O6fTITmem3j6MhNVKp4WqNwnCjh1rnLVQ2FWokSsPEHj7d3BbA05J nD3LA4QWe0txeNhMDkGP5OBTkeexDNNx1UJqOdGFuRzdYsQNKcs7WLVVwzvZ0gRgNXze W8Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776274846; x=1776879646; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1mmHtcDWBE7cV3MaI0SOK53oi2aQIxBNXcDXsA8cCN0=; b=e6NEfmnpkklWcRGudKFBLldAhUS4nr8BwjL+IkKr8SGTrb7Mj0bAFWENxYE0goMtOf /hRrFXUJsEnmUDDtFHAl4jvHurcmWZrFszKpoXNfQ7nN5Qj4t5T3/37HVrbXM/s7K4/h t8WIntf8ds7YMxnMcrH4VmPEeU3UtS8DxjlG9Bg+bhRZ9Rt9trghK73OOXqk02lbOqDd i8zmkOLtPCBs3AHZlBWldW979KTq47JCm34Y6sOTtmrlpNqbggVyG5OGIPOjleD7iQqA 56M8S77qJM6DCcsurSE9d1c7WwHY/mW21F2Tu4D03D12m8z2NZdmq66/6VsEbQhRWJnL hHzA== X-Forwarded-Encrypted: i=1; AFNElJ/ohAXuXOue+W5k3RDALfJ2pMLoS7U9h+KOK11hWya+Nqv1Bfg7wVMByaHk3yIKVd/6LYSjkIJuFuM5l18=@vger.kernel.org X-Gm-Message-State: AOJu0YykbFkFUNNCDPNuRLslHUuoIawHP2iZXZRwgQ12+PLveOAKWD50 +YJ6B+ZHDrzKyKyvkYqlcuWe4ronCZh4AQEY9h5SM2uaE3Y4p57SxP/qO8Yh2FT+ X-Gm-Gg: AeBDievAtvpUpwl8W0FOGgnIXeTjBJiTUKYRCkZJg+8YSxIygpHENcfkSPBclThn/mY 5lcsPjOYaDsBZDKB4jiQ+u+1tUJTDwxgUtbGCmItwSiwt5oQYt2GGyCADNexnnULnjplxAIx5ym xpmGN1NFfNCTB3EBcS1mAYen0mgsqwZz5Kg2Cj0NiPfkI5maS2sMv9L4qHdiQesmT4eTtLROyFq +4jTXnxqbe26C77MsrG9T1vmBqa23WZKs69pkr8zV237Q+QETdoDxbVKlNQMZYvI7PBbfF5/UNJ kWhOiwim1jYUUYx0iji7fDd9B4hTpVcrLbPfO8Sfd6x4PPJJpxEP8rJ01Y+x8Y1t/g8TgE1KTUB 76Eq1o+QuI3iKzDE2GRLHvWzSjJrpkhw3cjbhTYA2XtVWaS6k2BIyljoIsAEueQCXbjKF8Q4Xmg A9jd8GTxxhcP7optUccVET21wT1li9nIuaG6UOuqZs7NKuFD7IcBzj498IrxrU4InzDgSKJb+cj n78cRV3CdThJ0EzBv9+993bdbkkDaSigk1SuA== X-Received: by 2002:a17:90a:d446:b0:35b:d795:cf5d with SMTP id 98e67ed59e1d1-3612f2aea19mr315597a91.5.1776274845920; Wed, 15 Apr 2026 10:40:45 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35fd1fe9b50sm2891026a91.3.2026.04.15.10.40.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 10:40:45 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v1 3/4] virtio: add noirq system sleep PM infrastructure Date: Thu, 16 Apr 2026 02:38:32 +0900 Message-Id: <20260415173833.6319-4-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415173833.6319-1-baver.bae@gmail.com> References: <20260415173833.6319-1-baver.bae@gmail.com> 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 Content-Type: text/plain; charset="utf-8" From: Sungho Bae Some virtio-mmio devices, such as virtio-clock or virtio-regulator, must become operational before the regular PM restore callback runs because other devices may depend on them. Add the core infrastructure needed to support noirq system-sleep PM callbacks for virtio transports: - virtio_add_status_noirq(): status helper without might_sleep(). - virtio_features_ok_noirq(): feature negotiation without might_sleep(). - virtio_reset_device_noirq(): device reset that skips virtio_synchronize_cbs() (IRQ handlers are already quiesced in the noirq phase). - virtio_device_reinit_noirq(): full noirq bring-up sequence using the above helpers. - virtio_config_core_enable_noirq(): config enable with irqsave locking. - virtio_device_ready_noirq(): marks DRIVER_OK without virtio_synchronize_cbs(). Add freeze_noirq/restore_noirq callbacks to struct virtio_driver and provide matching helper wrappers in the virtio core: - virtio_device_freeze_noirq(): forwards to drv->freeze_noirq(). - virtio_device_restore_noirq(): runs the noirq bring-up sequence, resets existing vrings via the new config_ops->reset_vqs() hook, then calls drv->restore_noirq(). Modify virtio_device_restore() so that when a driver provides restore_noirq, the normal-phase restore skips the re-initialization that was already done in the noirq phase. Signed-off-by: Sungho Bae --- drivers/virtio/virtio.c | 172 +++++++++++++++++++++++++++++++++- include/linux/virtio.h | 8 ++ include/linux/virtio_config.h | 29 ++++++ 3 files changed, 206 insertions(+), 3 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index b0668434ac21..4fcb6b8c797f 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -193,6 +193,17 @@ static void virtio_config_core_enable(struct virtio_de= vice *dev) spin_unlock_irq(&dev->config_lock); } =20 +static void virtio_config_core_enable_noirq(struct virtio_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->config_lock, flags); + dev->config_core_enabled =3D true; + if (dev->config_change_pending) + __virtio_config_changed(dev); + spin_unlock_irqrestore(&dev->config_lock, flags); +} + void virtio_add_status(struct virtio_device *dev, unsigned int status) { might_sleep(); @@ -200,6 +211,20 @@ void virtio_add_status(struct virtio_device *dev, unsi= gned int status) } EXPORT_SYMBOL_GPL(virtio_add_status); =20 +/* + * Same as virtio_add_status() but without the might_sleep() assertion, + * so it is safe to call from noirq context. + * + * This assumes that the device's get_status and set_status operations are + * also noirq-safe. Therefore, the device must garantee that get_status and + * set_status can be called from noirq context. + */ +void virtio_add_status_noirq(struct virtio_device *dev, unsigned int statu= s) +{ + dev->config->set_status(dev, dev->config->get_status(dev) | status); +} +EXPORT_SYMBOL_GPL(virtio_add_status_noirq); + /* Do some validation, then set FEATURES_OK */ static int virtio_features_ok(struct virtio_device *dev) { @@ -234,6 +259,38 @@ static int virtio_features_ok(struct virtio_device *de= v) return 0; } =20 +/* noirq-safe variant: no might_sleep(), uses virtio_add_status_noirq() */ +static int virtio_features_ok_noirq(struct virtio_device *dev) +{ + unsigned int status; + + if (virtio_check_mem_acc_cb(dev)) { + if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) { + dev_warn(&dev->dev, + "device must provide VIRTIO_F_VERSION_1\n"); + return -ENODEV; + } + + if (!virtio_has_feature(dev, VIRTIO_F_ACCESS_PLATFORM)) { + dev_warn(&dev->dev, + "device must provide VIRTIO_F_ACCESS_PLATFORM\n"); + return -ENODEV; + } + } + + if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) + return 0; + + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FEATURES_OK); + status =3D dev->config->get_status(dev); + if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { + dev_err(&dev->dev, "virtio: device refuses features: %x\n", + status); + return -ENODEV; + } + return 0; +} + /** * virtio_reset_device - quiesce device for removal * @dev: the device to reset @@ -267,6 +324,24 @@ void virtio_reset_device(struct virtio_device *dev) } EXPORT_SYMBOL_GPL(virtio_reset_device); =20 +/** + * virtio_reset_device_noirq - noirq-safe variant of virtio_reset_device() + * @dev: the device to reset + */ +void virtio_reset_device_noirq(struct virtio_device *dev) +{ +#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION + /* + * The noirq stage runs with device IRQ handlers disabled, so + * virtio_synchronize_cbs() must not be called here. + */ + virtio_break_device(dev); +#endif + + dev->config->reset(dev); +} +EXPORT_SYMBOL_GPL(virtio_reset_device_noirq); + static int virtio_dev_probe(struct device *_d) { int err, i; @@ -618,6 +693,41 @@ static int virtio_device_reinit(struct virtio_device *= dev) return virtio_features_ok(dev); } =20 +/* noirq-safe variant of virtio_device_reinit() */ +static int virtio_device_reinit_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + /* + * We always start by resetting the device, in case a previous + * driver messed it up. + */ + virtio_reset_device_noirq(dev); + + /* Acknowledge that we've seen the device. */ + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); + + /* + * Maybe driver failed before freeze. + * Restore the failed status, for debugging. + */ + if (dev->failed) + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FAILED); + + if (!drv) + return 0; + + /* We have a driver! */ + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_DRIVER); + + ret =3D dev->config->finalize_features(dev); + if (ret) + return ret; + + return virtio_features_ok_noirq(dev); +} + #ifdef CONFIG_PM_SLEEP int virtio_device_freeze(struct virtio_device *dev) { @@ -645,9 +755,15 @@ int virtio_device_restore(struct virtio_device *dev) struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); int ret; =20 - ret =3D virtio_device_reinit(dev); - if (ret) - goto err; + /* + * If this device was already brought up in the noirq phase, + * skip the re-initialization here. + */ + if (!drv || !drv->restore_noirq) { + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + } =20 if (drv && drv->restore) { ret =3D drv->restore(dev); @@ -668,6 +784,56 @@ int virtio_device_restore(struct virtio_device *dev) return ret; } EXPORT_SYMBOL_GPL(virtio_device_restore); + +int virtio_device_freeze_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + + if (drv && drv->freeze_noirq) + return drv->freeze_noirq(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(virtio_device_freeze_noirq); + +int virtio_device_restore_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + if (!drv || !drv->restore_noirq) + return 0; + + ret =3D virtio_device_reinit_noirq(dev); + if (ret) + goto err; + + if (!list_empty(&dev->vqs)) { + if (!dev->config->reset_vqs) { + ret =3D -EOPNOTSUPP; + goto err; + } + + ret =3D dev->config->reset_vqs(dev); + if (ret) + goto err; + } + + ret =3D drv->restore_noirq(dev); + if (ret) + goto err; + + /* If restore_noirq set DRIVER_OK, enable config now. */ + if (dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK) + virtio_config_core_enable_noirq(dev); + + return 0; + +err: + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FAILED); + return ret; +} +EXPORT_SYMBOL_GPL(virtio_device_restore_noirq); #endif =20 int virtio_device_reset_prepare(struct virtio_device *dev) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 3bbc4cb6a672..31267334e4de 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -209,8 +209,12 @@ void virtio_config_driver_enable(struct virtio_device = *dev); #ifdef CONFIG_PM_SLEEP int virtio_device_freeze(struct virtio_device *dev); int virtio_device_restore(struct virtio_device *dev); +int virtio_device_freeze_noirq(struct virtio_device *dev); +int virtio_device_restore_noirq(struct virtio_device *dev); #endif void virtio_reset_device(struct virtio_device *dev); +void virtio_reset_device_noirq(struct virtio_device *dev); +void virtio_add_status_noirq(struct virtio_device *dev, unsigned int statu= s); int virtio_device_reset_prepare(struct virtio_device *dev); int virtio_device_reset_done(struct virtio_device *dev); =20 @@ -237,6 +241,8 @@ size_t virtio_max_dma_size(const struct virtio_device *= vdev); * changes; may be called in interrupt context. * @freeze: optional function to call during suspend/hibernation. * @restore: optional function to call on resume. + * @freeze_noirq: optional function to call during noirq suspend/hibernati= on. + * @restore_noirq: optional function to call on noirq resume. * @reset_prepare: optional function to call when a transport specific res= et * occurs. * @reset_done: optional function to call after transport specific reset @@ -258,6 +264,8 @@ struct virtio_driver { void (*config_changed)(struct virtio_device *dev); int (*freeze)(struct virtio_device *dev); int (*restore)(struct virtio_device *dev); + int (*freeze_noirq)(struct virtio_device *dev); + int (*restore_noirq)(struct virtio_device *dev); int (*reset_prepare)(struct virtio_device *dev); int (*reset_done)(struct virtio_device *dev); void (*shutdown)(struct virtio_device *dev); diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 69f84ea85d71..496897bc417e 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -70,6 +70,9 @@ struct virtqueue_info { * vqs_info: array of virtqueue info structures * Returns 0 on success or error status * @del_vqs: free virtqueues found by find_vqs(). + * @reset_vqs: reinitialize existing virtqueues without allocating or + * freeing them (optional). Used during noirq restore. + * Returns 0 on success or error status. * @synchronize_cbs: synchronize with the virtqueue callbacks (optional) * The function guarantees that all memory operations on the * queue before it are visible to the vring_interrupt() that is @@ -123,6 +126,7 @@ struct virtio_config_ops { struct virtqueue_info vqs_info[], struct irq_affinity *desc); void (*del_vqs)(struct virtio_device *); + int (*reset_vqs)(struct virtio_device *vdev); void (*synchronize_cbs)(struct virtio_device *); u64 (*get_features)(struct virtio_device *vdev); void (*get_extended_features)(struct virtio_device *vdev, @@ -371,6 +375,31 @@ void virtio_device_ready(struct virtio_device *dev) dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK); } =20 +/** + * virtio_device_ready_noirq - noirq-safe variant of virtio_device_ready() + * @dev: the virtio device + * + * This assumes that the device's get_status and set_status operations are + * noirq-safe. + */ +static inline +void virtio_device_ready_noirq(struct virtio_device *dev) +{ + unsigned int status =3D dev->config->get_status(dev); + + WARN_ON(status & VIRTIO_CONFIG_S_DRIVER_OK); + +#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION + /* + * The noirq stage runs with device IRQ handlers disabled, so + * virtio_synchronize_cbs() must not be called here. + */ + __virtio_unbreak_device(dev); +#endif + + dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK); +} + static inline const char *virtio_bus_name(struct virtio_device *vdev) { --=20 2.34.1 From nobody Sat Jun 20 11:49:36 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 2E15F3ED12D for ; Wed, 15 Apr 2026 17:40:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274850; cv=none; b=QQjEfQw8PR/+cP/ETtuuexNBCZIwRL/whU34kiaRIM859ExJyuTO3H4YzrGO7AcL0qOSAjntPY3stog+FWxxdO9n0wMlftVm43zx5ZfUtbhqwROkG+aLgoOV0N60xwpf6lFNgFDKO8+uRc7NAkEy5+jvFEyyqkWEVOWjJNQZ8ro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776274850; c=relaxed/simple; bh=wM41XmBBS8TtNKAIUom+SJe3wlh1BXsYctp8oV5NbHA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=BDuuHVibsms9Bn1U0IEs1cMOS/UXT4gFzD5hHan7a36ZwhmphUw5c95xONiHDziAj7BkucUYsLqkHtQ2voVzrijTJQul2GHLFQLYyk/LdxYtquyAIxslwAbWaTl9pv+J/yOaLKUO+5zlbYRVbstxYZYGwZRu7kpam9Yb2q5U62U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=od9UVH/u; arc=none smtp.client-ip=209.85.216.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="od9UVH/u" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-358e3cc5e7eso3865133a91.0 for ; Wed, 15 Apr 2026 10:40:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776274848; x=1776879648; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wM7k7U3YOg606LvkeNC0T6FE9JAmhA/+H8CjM9x4H8o=; b=od9UVH/u0tzvwoMpDkE3tvJS3e73cpHxAE0ItMRt3fp0oKOmebj3CHITtgJZYQqB9x V8HB5R5bMnSuwNoITPZrklk1vEj78L2aob8qz1edUPxQDc8JbDj8jjcINz1B7RjGhVpM hegYZZz9afVSXEcBdtgYKAK9XT3+6Gxbsp+LIv/gWY9ursiCyABdF9b0XITcZUdz2d9K VVc1SRWQw9aP8yXq0QAuuT7hYyhv3Wmc6gYCXBx3LKTQa4W30Wf084xvhI+B+xwz0myS ty6BELgWqcyLjnvtP4fp/mcRMWWWgULtItzQp1/ZCUhkiGvI8aCrUv8qAQb+FaPAlFF6 m3ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776274848; x=1776879648; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wM7k7U3YOg606LvkeNC0T6FE9JAmhA/+H8CjM9x4H8o=; b=ZQulUog5VbefA6S0n7BUPRTkbHsI+GyT1NBFfY2e/QzFgQ1AA1/rFWhsAeHEMnTnS/ Wfn6iJ67VhA0q0+6buhmFGjaL4TWI0MnCgCnZmUlzdZv25TvIgc063EitxhJj9y+gY58 mIBAuhNEe8YSftMcFQPrMm4wl+NmAzs41z5Shvc7sEb+XC/2UabyN5jAcTkQJTfbPdc9 2MhzlnItRMCR+JHdvoiOXxeN2zdTMG12anJBX8ViLIsbYfrJXhEPr3zy4Tjnb5pGYO7Z f2pqyz7lCSJaVTlVjjWE7GxYKprmLfykGH5MB49Xsr90pu0OLjpk9XzNVvGW63P3Fm1A 8qhQ== X-Forwarded-Encrypted: i=1; AFNElJ/jOoSZy3oEN9C8WXAgFC6pQ2TvizN+mfodtcqHKyGyJPWZLFOCttzG5/yqwRfI2kvVAhSbt3cyVCr5MTo=@vger.kernel.org X-Gm-Message-State: AOJu0Yzt4uepNFwFCOduacu8OxIjF+F//AETf91TcqdkhOH+FkmW2Wum Z1/tLFR5mevjEFh5JkOhWo7oLy6LUm10ysIIIzpL/qRYh9Xb8EAxFVe29sYvYp6m X-Gm-Gg: AeBDiev4DvH+oVw2J2hrnFdcdJ5MsrEVmsdRBbTl8Bn3mByK1bAAcPVqJ17WXtGpR31 +z4rsZc6Fvo0S8DBlELIn1o/GyooypVFOylZJ29CUIs0RmycrcAhnLkr8+4JhXhxGEj1QVVVnjX wkcBW1Gll1fUwvXOHoQvjypdlx/UysK1UEPMfWIeWws8ewEy96QduC7ifh71RD0SDuQHQSUr0u5 nbnlf1Cu2IlCmS8GLVmkfzUOcUmgq0wlDvJoIA3iBM0iWPsSnV7NhJUPmHIwkc3zC69DBlipf+0 AWqhY027bp1EoIbjEMvpSn0rCcPnJEYTLhOVHesZ4zfiM4i59o51V3fc0I4pgutpAd3Msfrbr/j P7N4HF1gscYgCAgayMhQ2ghjbrVYOwMUXY4gVNGTqU2cd37k29Flt46Pk5IVdxfujNRObGGQCZ8 OP2Vq7Y/Q2yV2eJ5dPAPhQOXcwVjLG4sBhDijtAdl/f6qmOdDBYCuAANdz89ZxBNTJdtJ9GD7vD s4fBR/3xVx1gxJUlqNotjDKbY6Kp/woEXlwLA== X-Received: by 2002:a17:90a:d407:b0:35e:594a:5b75 with SMTP id 98e67ed59e1d1-35e594a62e8mr14176643a91.25.1776274848384; Wed, 15 Apr 2026 10:40:48 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35fd1fe9b50sm2891026a91.3.2026.04.15.10.40.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 10:40:48 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v1 4/4] virtio-mmio: wire up noirq system sleep PM callbacks Date: Thu, 16 Apr 2026 02:38:33 +0900 Message-Id: <20260415173833.6319-5-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415173833.6319-1-baver.bae@gmail.com> References: <20260415173833.6319-1-baver.bae@gmail.com> 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 Content-Type: text/plain; charset="utf-8" From: Sungho Bae Implement the transport side of noirq system-sleep PM for virtio-mmio: - vm_reset_vqs(): iterate all virtqueues, call virtqueue_reinit_vring() to reset the vring state in place, then reprogram the MMIO queue registers (QUEUE_SEL, QUEUE_NUM, descriptor/avail/used addresses, QUEUE_READY) so the device can use the same rings immediately after restore. No memory is allocated or freed. - virtio_mmio_freeze_noirq() / virtio_mmio_restore_noirq(): thin wrappers that forward to the virtio core noirq helpers. The restore_noirq path also writes GUEST_PAGE_SIZE for legacy (v1) devices, matching the existing restore callback. - Wire vm_reset_vqs into virtio_mmio_config_ops and register the noirq callbacks via SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(). With this in place, a virtio-mmio driver can implement freeze_noirq / restore_noirq to participate in the noirq PM phase, enabling use cases such as virtio-clock or virtio-regulator that must be operational before other devices are restored. Signed-off-by: Sungho Bae --- drivers/virtio/virtio_mmio.c | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 595c2274fbb5..7bf193ba4173 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -336,6 +336,65 @@ static void vm_del_vqs(struct virtio_device *vdev) free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); } =20 +static int vm_reset_vqs(struct virtio_device *vdev) +{ + struct virtio_mmio_device *vm_dev =3D to_virtio_mmio_device(vdev); + struct virtqueue *vq; + + virtio_device_for_each_vq(vdev, vq) { + unsigned int num =3D virtqueue_get_vring_size(vq); + + virtqueue_reinit_vring(vq); + + writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); + writel(num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); + + if (vm_dev->version =3D=3D 1) { + u64 q_pfn =3D virtqueue_get_desc_addr(vq) >> PAGE_SHIFT; + + /* + * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have + * something that doesn't fit in 32bit, fail the setup + * rather than pretending to be successful. + */ + if (q_pfn >> 32) { + dev_err(&vdev->dev, + "platform bug: legacy virtio-mmio must not be used with RAM above 0x%= llxGB\n", + 0x1ULL << (32 + PAGE_SHIFT - 30)); + return -E2BIG; + } + + writel(PAGE_SIZE, + vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); + writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); + } else { + u64 addr; + + addr =3D virtqueue_get_desc_addr(vq); + writel((u32)addr, + vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); + + addr =3D virtqueue_get_avail_addr(vq); + writel((u32)addr, + vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); + + addr =3D virtqueue_get_used_addr(vq); + writel((u32)addr, + vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); + + writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); + } + } + + return 0; +} + static void vm_synchronize_cbs(struct virtio_device *vdev) { struct virtio_mmio_device *vm_dev =3D to_virtio_mmio_device(vdev); @@ -528,6 +587,7 @@ static const struct virtio_config_ops virtio_mmio_confi= g_ops =3D { .reset =3D vm_reset, .find_vqs =3D vm_find_vqs, .del_vqs =3D vm_del_vqs, + .reset_vqs =3D vm_reset_vqs, .get_features =3D vm_get_features, .finalize_features =3D vm_finalize_features, .bus_name =3D vm_bus_name, @@ -553,8 +613,27 @@ static int virtio_mmio_restore(struct device *dev) return virtio_device_restore(&vm_dev->vdev); } =20 +static int virtio_mmio_freeze_noirq(struct device *dev) +{ + struct virtio_mmio_device *vm_dev =3D dev_get_drvdata(dev); + + return virtio_device_freeze_noirq(&vm_dev->vdev); +} + +static int virtio_mmio_restore_noirq(struct device *dev) +{ + struct virtio_mmio_device *vm_dev =3D dev_get_drvdata(dev); + + if (vm_dev->version =3D=3D 1) + writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); + + return virtio_device_restore_noirq(&vm_dev->vdev); +} + static const struct dev_pm_ops virtio_mmio_pm_ops =3D { SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze_noirq, + virtio_mmio_restore_noirq) }; #endif =20 --=20 2.34.1