From patchwork Wed Jun 20 17:42:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Siqueira X-Patchwork-Id: 10478295 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 274AF601D7 for ; Wed, 20 Jun 2018 17:42:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E0A628D75 for ; Wed, 20 Jun 2018 17:42:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0207528DBB; Wed, 20 Jun 2018 17:42:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7DAB128D75 for ; Wed, 20 Jun 2018 17:42:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0F8286E604; Wed, 20 Jun 2018 17:42:35 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt0-x242.google.com (mail-qt0-x242.google.com [IPv6:2607:f8b0:400d:c0d::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id E268B6E604 for ; Wed, 20 Jun 2018 17:42:33 +0000 (UTC) Received: by mail-qt0-x242.google.com with SMTP id o9-v6so380872qtp.3 for ; Wed, 20 Jun 2018 10:42:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=PjV/pyitqX/QA9z9PmO3905Gh5v0WhU1mezkUIlJsNA=; b=n68eX485MI5R6ds+mgcdhKAJZq98x8wmHWZZQM1wcsm7+TxpyzEDalC/p0Z4zXEwWe VfpOXoTTzT2PBh4r+SY4AdGYYf7rvi3tjecn51bBzanLDa9oRAjSjK7Y/t24g2I1b7XL 2pGaOx94zAmySU+79G4mnSxwAzcBWoWrGNi0gcxvoY259Q3aXVVO4BvuFjUWqjEMU+Ea 5OvIrPtCW6sNVu/1NCwE/IWcdh3NFDG1zZ93k/Jp19dwV9k7IYEU7XJ4RDPzVESmkRPV sBDQ+lYV6Zb9zUrXinae29wO4SL716Q6Z/36HYA+Q/TbGNlElhvDyr6zl+WZVp6aciYo fe4g== X-Gm-Message-State: APt69E2gYL/+srApSTJcgn+03/viw0VPzo8pgB/dR2VSW//xT9Ph26rs dEKMF0TNwjHqHX7kW4F+jrA= X-Google-Smtp-Source: ADUXVKKORt3a5SzMwfcdTyWYp1g5FqP2ic1LrSIexHAgo8+G3AashBUbz+YnG5Bv37eSDxmSX+JXDw== X-Received: by 2002:a0c:e50b:: with SMTP id l11-v6mr19428612qvm.21.1529516553012; Wed, 20 Jun 2018 10:42:33 -0700 (PDT) Received: from smtp.gmail.com ([143.107.45.1]) by smtp.gmail.com with ESMTPSA id g8-v6sm1730259qtp.9.2018.06.20.10.42.31 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 20 Jun 2018 10:42:32 -0700 (PDT) Date: Wed, 20 Jun 2018 14:42:29 -0300 From: Rodrigo Siqueira To: Gustavo Padovan , Sean Paul , Daniel Vetter , Haneen Mohammed Subject: [PATCH] drm/vkms: Add dumb operations Message-ID: <20180620174229.pkkba3fgam52vr3h@smtp.gmail.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20180512 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP VKMS currently does not handle dumb data, and as a consequence, it does not provide mechanisms for handling gem. This commit adds the necessary support for gem object/handler and the dumb functions. Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/vkms/Makefile | 2 +- drivers/gpu/drm/vkms/vkms_drv.c | 9 ++ drivers/gpu/drm/vkms/vkms_drv.h | 21 ++++ drivers/gpu/drm/vkms/vkms_gem.c | 168 ++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vkms/vkms_gem.c diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 3f774a6a9c58..986297da51bf 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,3 +1,3 @@ -vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o +vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o obj-$(CONFIG_DRM_VKMS) += vkms.o diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 740a4cbfed91..638bab9083b5 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -37,6 +37,12 @@ static const struct file_operations vkms_driver_fops = { .release = drm_release, }; +static const struct vm_operations_struct vkms_gem_vm_ops = { + .fault = vkms_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + static void vkms_release(struct drm_device *dev) { struct vkms_device *vkms = container_of(dev, struct vkms_device, drm); @@ -50,6 +56,9 @@ static struct drm_driver vkms_driver = { .driver_features = DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM, .release = vkms_release, .fops = &vkms_driver_fops, + .dumb_create = vkms_dumb_create, + .dumb_map_offset = vkms_dumb_map, + .gem_vm_ops = &vkms_gem_vm_ops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index b0f9d2e61a42..54bb3dd2b2c1 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -3,6 +3,7 @@ #include #include +#include #include static const u32 vkms_formats[] = { @@ -21,6 +22,12 @@ struct vkms_device { struct vkms_output output; }; +struct vkms_gem_object { + struct drm_gem_object gem; + struct mutex pages_lock; /* Page lock used in page fault handler */ + struct page **pages; +}; + int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor); @@ -28,4 +35,18 @@ int vkms_output_init(struct vkms_device *vkmsdev); struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev); +/* Gem stuff */ +struct drm_gem_object *vkms_gem_create(struct drm_device *dev, + struct drm_file *file, + u32 *handle, + u64 size); + +int vkms_gem_fault(struct vm_fault *vmf); + +int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, + struct drm_mode_create_dumb *args); + +int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, + u32 handle, u64 *offset); + #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c new file mode 100644 index 000000000000..9f820f56b9e0 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +#include "vkms_drv.h" + +static struct vkms_gem_object *__vkms_gem_create(struct drm_device *dev, + u64 size) +{ + struct vkms_gem_object *obj; + int ret; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return ERR_PTR(-ENOMEM); + + size = roundup(size, PAGE_SIZE); + ret = drm_gem_object_init(dev, &obj->gem, size); + if (ret) { + kfree(obj); + return ERR_PTR(ret); + } + + mutex_init(&obj->pages_lock); + + return obj; +} + +int vkms_gem_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct vkms_gem_object *obj = vma->vm_private_data; + unsigned long vaddr = vmf->address; + pgoff_t page_offset; + loff_t num_pages; + int ret; + + page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT; + num_pages = DIV_ROUND_UP(obj->gem.size, PAGE_SIZE); + + if (page_offset > num_pages) + return VM_FAULT_SIGBUS; + + ret = -ENOENT; + mutex_lock(&obj->pages_lock); + if (obj->pages) { + get_page(obj->pages[page_offset]); + vmf->page = obj->pages[page_offset]; + ret = 0; + } + mutex_unlock(&obj->pages_lock); + if (ret) { + struct page *page; + struct address_space *mapping; + + mapping = file_inode(obj->gem.filp)->i_mapping; + page = shmem_read_mapping_page(mapping, page_offset); + + if (!IS_ERR(page)) { + vmf->page = page; + ret = 0; + } else { + switch (PTR_ERR(page)) { + case -ENOSPC: + case -ENOMEM: + ret = VM_FAULT_OOM; + break; + case -EBUSY: + ret = VM_FAULT_RETRY; + break; + case -EFAULT: + case -EINVAL: + ret = VM_FAULT_SIGBUS; + break; + default: + WARN_ON(PTR_ERR(page)); + ret = VM_FAULT_SIGBUS; + break; + } + } + } + return ret; +} + +struct drm_gem_object *vkms_gem_create(struct drm_device *dev, + struct drm_file *file, + u32 *handle, + u64 size) +{ + struct vkms_gem_object *obj; + int ret; + + if (!file || !dev || !handle) + return ERR_PTR(-EINVAL); + + obj = __vkms_gem_create(dev, size); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + ret = drm_gem_handle_create(file, &obj->gem, handle); + drm_gem_object_put_unlocked(&obj->gem); + if (ret) { + drm_gem_object_release(&obj->gem); + kfree(obj); + return ERR_PTR(ret); + } + + return &obj->gem; +} + +int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct drm_gem_object *gem_obj; + u64 pitch, size; + + if (!args || !dev || !file) + return -EINVAL; + + pitch = args->width * DIV_ROUND_UP(args->bpp, 8); + size = pitch * args->height; + + if (!size) + return -EINVAL; + + gem_obj = vkms_gem_create(dev, file, &args->handle, size); + if (IS_ERR(gem_obj)) + return PTR_ERR(gem_obj); + + args->size = gem_obj->size; + args->pitch = pitch; + + DRM_DEBUG_DRIVER("Created object of size %lld\n", size); + + return 0; +} + +int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, + u32 handle, u64 *offset) +{ + struct drm_gem_object *obj; + int ret; + + obj = drm_gem_object_lookup(file, handle); + if (!obj) + return -ENOENT; + + if (!obj->filp) { + ret = -EINVAL; + goto unref; + } + + ret = drm_gem_create_mmap_offset(obj); + if (ret) + goto unref; + + *offset = drm_vma_node_offset_addr(&obj->vma_node); +unref: + drm_gem_object_put_unlocked(obj); + + return ret; +}