From patchwork Fri Dec 20 10:36:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inki Dae X-Patchwork-Id: 3387561 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 12292C0D4A for ; Fri, 20 Dec 2013 10:37:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 85C56206EA for ; Fri, 20 Dec 2013 10:37:11 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id AE146206E6 for ; Fri, 20 Dec 2013 10:37:09 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 571B7FA4BE; Fri, 20 Dec 2013 02:37:05 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by gabe.freedesktop.org (Postfix) with ESMTP id A347EFA4BD for ; Fri, 20 Dec 2013 02:37:00 -0800 (PST) Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MY3002SJPHMWJ20@mailout3.samsung.com> for dri-devel@lists.freedesktop.org; Fri, 20 Dec 2013 19:36:58 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.113]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 21.A5.12635.9CD14B25; Fri, 20 Dec 2013 19:36:57 +0900 (KST) X-AuditID: cbfee68d-b7fcd6d00000315b-f5-52b41dc9e00a Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 95.AF.29263.9CD14B25; Fri, 20 Dec 2013 19:36:57 +0900 (KST) Received: from daeinki-desktop.10.32.193.11 ([10.252.75.62]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MY300HPEPHLG840@mmp2.samsung.com>; Fri, 20 Dec 2013 19:36:57 +0900 (KST) From: Inki Dae To: airlied@linux.ie, dri-devel@lists.freedesktop.org Subject: [PATCH] drm/exynos: use a new anon file for exynos gem mmaper Date: Fri, 20 Dec 2013 19:36:55 +0900 Message-id: <1387535815-31880-1-git-send-email-inki.dae@samsung.com> X-Mailer: git-send-email 1.7.9.5 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrPLMWRmVeSWpSXmKPExsWyRsSkUPek7JYgg4tXFS16z51ksrjy9T2b xaT7E1gszja9Ybc4//c4qwOrx/ZvD1g97ncfZ/Lo27KK0WPTk7dMASxRXDYpqTmZZalF+nYJ XBnXn85gKphgVzHva2AD4ynjLkZODgkBE4mGGb9YIGwxiQv31rN1MXJxCAksZZT4tGcRO0zR h6kLoBLTGSXmnt/OAuF0M0nMmbWLCaSKTUBVYuKK+2wgtoiAqUTHpKVgY5kFMiUm979lBLGF BdwktnxbDVbPAlS/ctN5MJtXwEVi1/fVQNs4gLYpSMyZZAMyX0LgNZvEvpun2CHqBSS+TT7E AlEjK7HpADPEcZISB1fcYJnAKLiAkWEVo2hqQXJBcVJ6kaFecWJucWleul5yfu4mRmBgnv73 rHcH4+0D1ocYk4HGTWSWEk3OBwZ2Xkm8obGZkYWpiamxkbmlGWnCSuK8SQ+TgoQE0hNLUrNT UwtSi+KLSnNSiw8xMnFwSjUwckzewf5+YuXMU2Uyvh+yhJVy7jBbu9+YXXFvt2f74qivWlsW CZ6+ZRRVfUEl0SX4SO+3Z7IVpX+Dpt9m0gp5rDWZ+9+cO41vSrqrcre82P7ji6HANLNVmXuX SwfxGF35MveKuBXzmzunSs7OyOqY8mfD79U7olznl1xesksj3Kedsey/4HWhCUosxRmJhlrM RcWJAEDrU2ZiAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrDIsWRmVeSWpSXmKPExsVy+t9jQd2TsluCDL7skLDoPXeSyeLK1/ds FpPuT2CxONv0ht3i/N/jrA6sHtu/PWD1uN99nMmjb8sqRo9NT94yBbBENTDaZKQmpqQWKaTm JeenZOal2yp5B8c7x5uaGRjqGlpamCsp5CXmptoqufgE6Lpl5gBtVlIoS8wpBQoFJBYXK+nb YZoQGuKmawHTGKHrGxIE12NkgAYS1jBmXH86g6lggl3FvK+BDYynjLsYOTkkBEwkPkxdwAZh i0lcuLceyObiEBKYzigx9/x2Fginm0lizqxdTCBVbAKqEhNX3AfrEBEwleiYtJQFxGYWyJSY 3P+WEcQWFnCT2PJtNVg9C1D9yk3nwWxeAReJXd9Xs3cxcgBtU5CYM8lmAiP3AkaGVYyiqQXJ BcVJ6bmGesWJucWleel6yfm5mxjBYf9MagfjygaLQ4wCHIxKPLwNtpuDhFgTy4orcw8xSnAw K4nwPhTdEiTEm5JYWZValB9fVJqTWnyIMRlo+URmKdHkfGBM5pXEGxqbmBlZGpkbWhgZm5Mm rCTOe6DVOlBIID2xJDU7NbUgtQhmCxMHp1QDI7NLfIKA0vfG9sWZ920Vjz9YeOj+vmrePpW0 h8p2B9fpfriqdFftRQtffOyP45/OVz7WOaiuyC6XeZrDcc0i84khqpG8/8yeLXabnux4dM2T WYyxNr7Pllyxu3ud4UDfYtZpdS8Esn496Y661jJD8l+o+JqpPFPaOUU2On1f+sjVJCjuDVeG mxJLcUaioRZzUXEiAPvkI8y/AgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Cc: Kyungmin Park , viro@zeniv.linux.org.uk X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch resolves potential deadlock issue that can be incurred by changing file->f_op and filp->private_data to exynos specific mapper ops and gem object temporarily. To resolve this issue, this patch creates a new anon file dedicated to exynos specific mmaper, and making it used instead of existing one. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 21 +++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + drivers/gpu/drm/exynos/exynos_drm_gem.c | 74 ++++++------------------------- drivers/gpu/drm/exynos/exynos_drm_gem.h | 3 ++ 4 files changed, 38 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 22b8f5e..b5e5957 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -14,6 +14,8 @@ #include #include +#include + #include #include "exynos_drm_drv.h" @@ -150,9 +152,14 @@ static int exynos_drm_unload(struct drm_device *dev) return 0; } +static const struct file_operations exynos_drm_gem_fops = { + .mmap = exynos_drm_gem_mmap_buffer, +}; + static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) { struct drm_exynos_file_private *file_priv; + struct file *anon_filp; int ret; file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); @@ -167,6 +174,16 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) file->driver_priv = NULL; } + anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops, + NULL, 0); + if (IS_ERR(anon_filp)) { + kfree(file_priv); + return PTR_ERR(anon_filp); + } + + anon_filp->f_mode = FMODE_READ | FMODE_WRITE; + file_priv->anon_filp = anon_filp; + return ret; } @@ -179,6 +196,7 @@ static void exynos_drm_preclose(struct drm_device *dev, static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) { struct exynos_drm_private *private = dev->dev_private; + struct drm_exynos_file_private *file_priv; struct drm_pending_vblank_event *v, *vt; struct drm_pending_event *e, *et; unsigned long flags; @@ -204,6 +222,9 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) } spin_unlock_irqrestore(&dev->event_lock, flags); + file_priv = file->driver_priv; + if (file_priv->anon_filp) + fput(file_priv->anon_filp); kfree(file->driver_priv); file->driver_priv = NULL; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index eaa1966..0eaf5a2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -226,6 +226,7 @@ struct exynos_drm_ipp_private { struct drm_exynos_file_private { struct exynos_drm_g2d_private *g2d_priv; struct exynos_drm_ipp_private *ipp_priv; + struct file *anon_filp; }; /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 1ade191..49b8c9b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -338,46 +338,22 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, &args->offset); } -static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev, - struct file *filp) -{ - struct drm_file *file_priv; - - /* find current process's drm_file from filelist. */ - list_for_each_entry(file_priv, &drm_dev->filelist, lhead) - if (file_priv->filp == filp) - return file_priv; - - WARN_ON(1); - - return ERR_PTR(-EFAULT); -} - -static int exynos_drm_gem_mmap_buffer(struct file *filp, +int exynos_drm_gem_mmap_buffer(struct file *filp, struct vm_area_struct *vma) { struct drm_gem_object *obj = filp->private_data; struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); struct drm_device *drm_dev = obj->dev; struct exynos_drm_gem_buf *buffer; - struct drm_file *file_priv; unsigned long vm_size; int ret; + WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); + vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; vma->vm_private_data = obj; vma->vm_ops = drm_dev->driver->gem_vm_ops; - /* restore it to driver's fops. */ - filp->f_op = fops_get(drm_dev->driver->fops); - - file_priv = exynos_drm_find_drm_file(drm_dev, filp); - if (IS_ERR(file_priv)) - return PTR_ERR(file_priv); - - /* restore it to drm_file. */ - filp->private_data = file_priv; - update_vm_cache_attr(exynos_gem_obj, vma); vm_size = vma->vm_end - vma->vm_start; @@ -411,15 +387,13 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, return 0; } -static const struct file_operations exynos_drm_gem_fops = { - .mmap = exynos_drm_gem_mmap_buffer, -}; - int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_exynos_file_private *exynos_file_priv; struct drm_exynos_gem_mmap *args = data; struct drm_gem_object *obj; + struct file *anon_filp; unsigned long addr; if (!(dev->driver->driver_features & DRIVER_GEM)) { @@ -427,47 +401,25 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, return -ENODEV; } + mutex_lock(&dev->struct_mutex); + obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (!obj) { DRM_ERROR("failed to lookup gem object.\n"); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } - /* - * We have to use gem object and its fops for specific mmaper, - * but vm_mmap() can deliver only filp. So we have to change - * filp->f_op and filp->private_data temporarily, then restore - * again. So it is important to keep lock until restoration the - * settings to prevent others from misuse of filp->f_op or - * filp->private_data. - */ - mutex_lock(&dev->struct_mutex); - - /* - * Set specific mmper's fops. And it will be restored by - * exynos_drm_gem_mmap_buffer to dev->driver->fops. - * This is used to call specific mapper temporarily. - */ - file_priv->filp->f_op = &exynos_drm_gem_fops; - - /* - * Set gem object to private_data so that specific mmaper - * can get the gem object. And it will be restored by - * exynos_drm_gem_mmap_buffer to drm_file. - */ - file_priv->filp->private_data = obj; + exynos_file_priv = file_priv->driver_priv; + anon_filp = exynos_file_priv->anon_filp; + anon_filp->private_data = obj; - addr = vm_mmap(file_priv->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, 0); + addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE, + MAP_SHARED, 0); drm_gem_object_unreference(obj); if (IS_ERR_VALUE(addr)) { - /* check filp->f_op, filp->private_data are restored */ - if (file_priv->filp->f_op == &exynos_drm_gem_fops) { - file_priv->filp->f_op = fops_get(dev->driver->fops); - file_priv->filp->private_data = file_priv; - } mutex_unlock(&dev->struct_mutex); return (int)addr; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 702ec3a..fde860c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -122,6 +122,9 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int exynos_drm_gem_mmap_buffer(struct file *filp, + struct vm_area_struct *vma); + /* map user space allocated by malloc to pages. */ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);