Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio: allow driver to disable the configure change notification

Sometime, it would be useful to disable the configure change
notification from the driver. So this patch allows this by introducing
a variable config_change_driver_disabled and only allow the configure
change notification callback to be triggered when it is allowed by
both the virtio core and the driver. It is set to false by default to
hold the current semantic so we don't need to change any drivers.

The first user for this would be virtio-net.

Cc: Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
Cc: Gia-Khanh Nguyen <gia-khanh.nguyen@oracle.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Link: https://patch.msgid.link/20240814052228.4654-3-jasowang@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jason Wang and committed by
Jakub Kicinski
224de6f8 0cb70ee4

+43 -3
+36 -3
drivers/virtio/virtio.c
··· 127 127 { 128 128 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); 129 129 130 - if (!dev->config_core_enabled) 130 + if (!dev->config_core_enabled || dev->config_driver_disabled) 131 131 dev->config_change_pending = true; 132 - else if (drv && drv->config_changed) 132 + else if (drv && drv->config_changed) { 133 133 drv->config_changed(dev); 134 + dev->config_change_pending = false; 135 + } 134 136 } 135 137 136 138 void virtio_config_changed(struct virtio_device *dev) ··· 144 142 spin_unlock_irqrestore(&dev->config_lock, flags); 145 143 } 146 144 EXPORT_SYMBOL_GPL(virtio_config_changed); 145 + 146 + /** 147 + * virtio_config_driver_disable - disable config change reporting by drivers 148 + * @dev: the device to reset 149 + * 150 + * This is only allowed to be called by a driver and disabling can't 151 + * be nested. 152 + */ 153 + void virtio_config_driver_disable(struct virtio_device *dev) 154 + { 155 + spin_lock_irq(&dev->config_lock); 156 + dev->config_driver_disabled = true; 157 + spin_unlock_irq(&dev->config_lock); 158 + } 159 + EXPORT_SYMBOL_GPL(virtio_config_driver_disable); 160 + 161 + /** 162 + * virtio_config_driver_enable - enable config change reporting by drivers 163 + * @dev: the device to reset 164 + * 165 + * This is only allowed to be called by a driver and enabling can't 166 + * be nested. 167 + */ 168 + void virtio_config_driver_enable(struct virtio_device *dev) 169 + { 170 + spin_lock_irq(&dev->config_lock); 171 + dev->config_driver_disabled = false; 172 + if (dev->config_change_pending) 173 + __virtio_config_changed(dev); 174 + spin_unlock_irq(&dev->config_lock); 175 + } 176 + EXPORT_SYMBOL_GPL(virtio_config_driver_enable); 147 177 148 178 static void virtio_config_core_disable(struct virtio_device *dev) 149 179 { ··· 190 156 dev->config_core_enabled = true; 191 157 if (dev->config_change_pending) 192 158 __virtio_config_changed(dev); 193 - dev->config_change_pending = false; 194 159 spin_unlock_irq(&dev->config_lock); 195 160 } 196 161
+7
include/linux/virtio.h
··· 119 119 * @index: unique position on the virtio bus 120 120 * @failed: saved value for VIRTIO_CONFIG_S_FAILED bit (for restore) 121 121 * @config_core_enabled: configuration change reporting enabled by core 122 + * @config_driver_disabled: configuration change reporting disabled by 123 + * a driver 122 124 * @config_change_pending: configuration change reported while disabled 123 125 * @config_lock: protects configuration change reporting 124 126 * @vqs_list_lock: protects @vqs. ··· 138 136 int index; 139 137 bool failed; 140 138 bool config_core_enabled; 139 + bool config_driver_disabled; 141 140 bool config_change_pending; 142 141 spinlock_t config_lock; 143 142 spinlock_t vqs_list_lock; ··· 169 166 void __virtqueue_unbreak(struct virtqueue *_vq); 170 167 171 168 void virtio_config_changed(struct virtio_device *dev); 169 + 170 + void virtio_config_driver_disable(struct virtio_device *dev); 171 + void virtio_config_driver_enable(struct virtio_device *dev); 172 + 172 173 #ifdef CONFIG_PM_SLEEP 173 174 int virtio_device_freeze(struct virtio_device *dev); 174 175 int virtio_device_restore(struct virtio_device *dev);