diff options
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_drv.c')
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.c | 178 |
1 files changed, 142 insertions, 36 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 2d1aaca49105..a5ce96fb8a1d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -26,36 +26,115 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <linux/aperture.h> #include <linux/module.h> -#include <linux/console.h> #include <linux/pci.h> -#include <drm/drmP.h> +#include <linux/poll.h> +#include <linux/vgaarb.h> +#include <linux/wait.h> + +#include <drm/clients/drm_client_setup.h> #include <drm/drm.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fbdev_shmem.h> +#include <drm/drm_file.h> +#include <drm/drm_print.h> #include "virtgpu_drv.h" -static struct drm_driver driver; + +#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050 + +static const struct drm_driver driver; static int virtio_gpu_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); module_param_named(modeset, virtio_gpu_modeset, int, 0400); +static int virtio_gpu_pci_quirk(struct drm_device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev->dev); + const char *pname = dev_name(&pdev->dev); + bool vga = pci_is_vga(pdev); + int ret; + + DRM_INFO("pci: %s detected at %s\n", + vga ? "virtio-vga" : "virtio-gpu-pci", + pname); + if (vga) { + ret = aperture_remove_conflicting_pci_devices(pdev, driver.name); + if (ret) + return ret; + } + + return 0; +} + static int virtio_gpu_probe(struct virtio_device *vdev) { - if (vgacon_text_force() && virtio_gpu_modeset == -1) + struct drm_device *dev; + int ret; + + if (drm_firmware_drivers_only() && virtio_gpu_modeset == -1) return -EINVAL; if (virtio_gpu_modeset == 0) return -EINVAL; - return drm_virtio_init(&driver, vdev); + /* + * The virtio-gpu device is a virtual device that doesn't have DMA + * ops assigned to it, nor DMA mask set and etc. Its parent device + * is actual GPU device we want to use it for the DRM's device in + * order to benefit from using generic DRM APIs. + */ + dev = drm_dev_alloc(&driver, vdev->dev.parent); + if (IS_ERR(dev)) + return PTR_ERR(dev); + vdev->priv = dev; + + if (dev_is_pci(vdev->dev.parent)) { + ret = virtio_gpu_pci_quirk(dev); + if (ret) + goto err_free; + } + + dma_set_max_seg_size(dev->dev, dma_max_mapping_size(dev->dev) ?: UINT_MAX); + ret = virtio_gpu_init(vdev, dev); + if (ret) + goto err_free; + + ret = drm_dev_register(dev, 0); + if (ret) + goto err_deinit; + + drm_client_setup(vdev->priv, NULL); + + return 0; + +err_deinit: + virtio_gpu_deinit(dev); +err_free: + drm_dev_put(dev); + return ret; } static void virtio_gpu_remove(struct virtio_device *vdev) { struct drm_device *dev = vdev->priv; - drm_put_dev(dev); + drm_dev_unplug(dev); + drm_atomic_helper_shutdown(dev); + virtio_gpu_deinit(dev); + drm_dev_put(dev); +} + +static void virtio_gpu_shutdown(struct virtio_device *vdev) +{ + struct drm_device *dev = vdev->priv; + + /* stop talking to the device */ + drm_dev_unplug(dev); } static void virtio_gpu_config_changed(struct virtio_device *vdev) @@ -81,19 +160,58 @@ static unsigned int features[] = { VIRTIO_GPU_F_VIRGL, #endif VIRTIO_GPU_F_EDID, + VIRTIO_GPU_F_RESOURCE_UUID, + VIRTIO_GPU_F_RESOURCE_BLOB, + VIRTIO_GPU_F_CONTEXT_INIT, }; static struct virtio_driver virtio_gpu_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtio_gpu_probe, .remove = virtio_gpu_remove, + .shutdown = virtio_gpu_shutdown, .config_changed = virtio_gpu_config_changed }; -module_virtio_driver(virtio_gpu_driver); +static int __init virtio_gpu_driver_init(void) +{ + struct pci_dev *pdev; + int ret; + + pdev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET, + PCI_DEVICE_ID_VIRTIO_GPU, + NULL); + if (pdev && pci_is_vga(pdev)) { + ret = vga_get_interruptible(pdev, + VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); + if (ret) { + pci_dev_put(pdev); + return ret; + } + } + + ret = register_virtio_driver(&virtio_gpu_driver); + + if (pdev) { + if (pci_is_vga(pdev)) + vga_put(pdev, + VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); + + pci_dev_put(pdev); + } + + return ret; +} + +static void __exit virtio_gpu_driver_exit(void) +{ + unregister_virtio_driver(&virtio_gpu_driver); +} + +module_init(virtio_gpu_driver_init); +module_exit(virtio_gpu_driver_exit); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Virtio GPU driver"); @@ -102,42 +220,29 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>"); MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); MODULE_AUTHOR("Alon Levy"); -static const struct file_operations virtio_gpu_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .mmap = virtio_gpu_mmap, - .poll = drm_poll, - .read = drm_read, - .unlocked_ioctl = drm_ioctl, - .release = drm_release, - .compat_ioctl = drm_compat_ioctl, - .llseek = noop_llseek, -}; +DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); -static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC, - .load = virtio_gpu_driver_load, - .unload = virtio_gpu_driver_unload, +static const struct drm_driver driver = { + /* + * If KMS is disabled DRIVER_MODESET and DRIVER_ATOMIC are masked + * out via drm_device::driver_features: + */ + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC | + DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | DRIVER_CURSOR_HOTSPOT, .open = virtio_gpu_driver_open, .postclose = virtio_gpu_driver_postclose, .dumb_create = virtio_gpu_mode_dumb_create, - .dumb_map_offset = virtio_gpu_mode_dumb_mmap, + + DRM_FBDEV_SHMEM_DRIVER_OPS, #if defined(CONFIG_DEBUG_FS) .debugfs_init = virtio_gpu_debugfs_init, #endif - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_pin = virtgpu_gem_prime_pin, - .gem_prime_unpin = virtgpu_gem_prime_unpin, - .gem_prime_vmap = virtgpu_gem_prime_vmap, - .gem_prime_vunmap = virtgpu_gem_prime_vunmap, - .gem_prime_mmap = virtgpu_gem_prime_mmap, - - .gem_free_object_unlocked = virtio_gpu_gem_free_object, - .gem_open_object = virtio_gpu_gem_object_open, - .gem_close_object = virtio_gpu_gem_object_close, + .gem_prime_import = virtgpu_gem_prime_import, + .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table, + + .gem_create_object = virtio_gpu_create_object, .fops = &virtio_gpu_driver_fops, .ioctls = virtio_gpu_ioctls, @@ -145,8 +250,9 @@ static struct drm_driver driver = { .name = DRIVER_NAME, .desc = DRIVER_DESC, - .date = DRIVER_DATE, .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, + + .release = virtio_gpu_release, }; |
