From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Daniel Vetter <daniel.vetter@ffwll.ch>,
Dave Airlie <airlied@redhat.com>
Subject: [ 30/73] drm/prime: keep a reference from the handle to exported dma-buf (v6)
Date: Thu, 9 May 2013 15:25:20 -0700 [thread overview]
Message-ID: <20130509222529.534649073@linuxfoundation.org> (raw)
In-Reply-To: <20130509222526.480204972@linuxfoundation.org>
3.9-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Airlie <airlied@gmail.com>
commit 219b47339ced80ca580bb6ce7d1636166984afa7 upstream.
Currently we have a problem with this:
1. i915: create gem object
2. i915: export gem object to prime
3. radeon: import gem object
4. close prime fd
5. radeon: unref object
6. i915: unref object
i915 has an imported object reference in its file priv, that isn't
cleaned up properly until fd close. The reference gets added at step 2,
but at step 6 we don't have enough info to clean it up.
The solution is to take a reference on the dma-buf when we export it,
and drop the reference when the gem handle goes away.
So when we export a dma_buf from a gem object, we keep track of it
with the handle, we take a reference to the dma_buf. When we close
the handle (i.e. userspace is finished with the buffer), we drop
the reference to the dma_buf, and it gets collected.
This patch isn't meant to fix any other problem or bikesheds, and it doesn't
fix any races with other scenarios.
v1.1: move export symbol line back up.
v2: okay I had to do a bit more, as the first patch showed a leak
on one of my tests, that I found using the dma-buf debugfs support,
the problem case is exporting a buffer twice with the same handle,
we'd add another export handle for it unnecessarily, however
we now fail if we try to export the same object with a different gem handle,
however I'm not sure if that is a case I want to support, and I've
gotten the code to WARN_ON if we hit something like that.
v2.1: rebase this patch, write better commit msg.
v3: cleanup error handling, track import vs export in linked list,
these two patches were separate previously, but seem to work better
like this.
v4: danvet is correct, this code is no longer useful, since the buffer
better exist, so remove it.
v5: always take a reference to the dma buf object, import or export.
(Imre Deak contributed this originally)
v6: square the circle, remove import vs export tracking now
that there is no difference
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_gem.c | 4 +-
drivers/gpu/drm/drm_prime.c | 76 +++++++++++++++++++++++---------------------
include/drm/drmP.h | 5 +-
3 files changed, 44 insertions(+), 41 deletions(-)
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -205,11 +205,11 @@ static void
drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
{
if (obj->import_attach) {
- drm_prime_remove_imported_buf_handle(&filp->prime,
+ drm_prime_remove_buf_handle(&filp->prime,
obj->import_attach->dmabuf);
}
if (obj->export_dma_buf) {
- drm_prime_remove_imported_buf_handle(&filp->prime,
+ drm_prime_remove_buf_handle(&filp->prime,
obj->export_dma_buf);
}
}
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -62,6 +62,7 @@ struct drm_prime_member {
struct dma_buf *dma_buf;
uint32_t handle;
};
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
@@ -200,7 +201,8 @@ int drm_gem_prime_handle_to_fd(struct dr
{
struct drm_gem_object *obj;
void *buf;
- int ret;
+ int ret = 0;
+ struct dma_buf *dmabuf;
obj = drm_gem_object_lookup(dev, file_priv, handle);
if (!obj)
@@ -209,43 +211,44 @@ int drm_gem_prime_handle_to_fd(struct dr
mutex_lock(&file_priv->prime.lock);
/* re-export the original imported object */
if (obj->import_attach) {
- get_dma_buf(obj->import_attach->dmabuf);
- *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags);
- drm_gem_object_unreference_unlocked(obj);
- mutex_unlock(&file_priv->prime.lock);
- return 0;
+ dmabuf = obj->import_attach->dmabuf;
+ goto out_have_obj;
}
if (obj->export_dma_buf) {
- get_dma_buf(obj->export_dma_buf);
- *prime_fd = dma_buf_fd(obj->export_dma_buf, flags);
- drm_gem_object_unreference_unlocked(obj);
- } else {
- buf = dev->driver->gem_prime_export(dev, obj, flags);
- if (IS_ERR(buf)) {
- /* normally the created dma-buf takes ownership of the ref,
- * but if that fails then drop the ref
- */
- drm_gem_object_unreference_unlocked(obj);
- mutex_unlock(&file_priv->prime.lock);
- return PTR_ERR(buf);
- }
- obj->export_dma_buf = buf;
- *prime_fd = dma_buf_fd(buf, flags);
+ dmabuf = obj->export_dma_buf;
+ goto out_have_obj;
}
+
+ buf = dev->driver->gem_prime_export(dev, obj, flags);
+ if (IS_ERR(buf)) {
+ /* normally the created dma-buf takes ownership of the ref,
+ * but if that fails then drop the ref
+ */
+ ret = PTR_ERR(buf);
+ goto out;
+ }
+ obj->export_dma_buf = buf;
+
/* if we've exported this buffer the cheat and add it to the import list
* so we get the correct handle back
*/
- ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
- obj->export_dma_buf, handle);
- if (ret) {
- drm_gem_object_unreference_unlocked(obj);
- mutex_unlock(&file_priv->prime.lock);
- return ret;
- }
+ ret = drm_prime_add_buf_handle(&file_priv->prime,
+ obj->export_dma_buf, handle);
+ if (ret)
+ goto out;
+ *prime_fd = dma_buf_fd(buf, flags);
mutex_unlock(&file_priv->prime.lock);
return 0;
+
+out_have_obj:
+ get_dma_buf(dmabuf);
+ *prime_fd = dma_buf_fd(dmabuf, flags);
+out:
+ drm_gem_object_unreference_unlocked(obj);
+ mutex_unlock(&file_priv->prime.lock);
+ return ret;
}
EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
@@ -317,7 +320,7 @@ int drm_gem_prime_fd_to_handle(struct dr
mutex_lock(&file_priv->prime.lock);
- ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime,
+ ret = drm_prime_lookup_buf_handle(&file_priv->prime,
dma_buf, handle);
if (!ret) {
ret = 0;
@@ -336,7 +339,7 @@ int drm_gem_prime_fd_to_handle(struct dr
if (ret)
goto out_put;
- ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
+ ret = drm_prime_add_buf_handle(&file_priv->prime,
dma_buf, *handle);
if (ret)
goto fail;
@@ -497,7 +500,7 @@ void drm_prime_destroy_file_private(stru
}
EXPORT_SYMBOL(drm_prime_destroy_file_private);
-int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
{
struct drm_prime_member *member;
@@ -505,14 +508,14 @@ int drm_prime_add_imported_buf_handle(st
if (!member)
return -ENOMEM;
+ get_dma_buf(dma_buf);
member->dma_buf = dma_buf;
member->handle = handle;
list_add(&member->entry, &prime_fpriv->head);
return 0;
}
-EXPORT_SYMBOL(drm_prime_add_imported_buf_handle);
-int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
+int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
{
struct drm_prime_member *member;
@@ -524,19 +527,20 @@ int drm_prime_lookup_imported_buf_handle
}
return -ENOENT;
}
-EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle);
+EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
-void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
{
struct drm_prime_member *member, *safe;
mutex_lock(&prime_fpriv->lock);
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
if (member->dma_buf == dma_buf) {
+ dma_buf_put(dma_buf);
list_del(&member->entry);
kfree(member);
}
}
mutex_unlock(&prime_fpriv->lock);
}
-EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle);
+EXPORT_SYMBOL(drm_prime_remove_buf_handle);
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1593,9 +1593,8 @@ extern void drm_prime_gem_destroy(struct
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
-int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
-void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
next prev parent reply other threads:[~2013-05-09 22:25 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-09 22:24 [ 00/73] 3.9.2-stable review Greg Kroah-Hartman
2013-05-09 22:24 ` [ 01/73] xen/arm: actually pass a non-NULL percpu pointer to request_percpu_irq Greg Kroah-Hartman
2013-05-09 22:24 ` [ 02/73] powerpc: Emulate non privileged DSCR read and write Greg Kroah-Hartman
2013-05-09 22:24 ` [ 03/73] powerpc/tm: Fix null pointer deference in flush_hash_page Greg Kroah-Hartman
2013-05-09 22:24 ` [ 04/73] powerpc: fix numa distance for form0 device tree Greg Kroah-Hartman
2013-05-09 22:24 ` [ 05/73] pwm: spear: Fix checking return value of clk_enable() and clk_prepare() Greg Kroah-Hartman
2013-05-09 22:24 ` [ 06/73] autofs - remove autofs dentry mount check Greg Kroah-Hartman
2013-05-09 22:24 ` [ 07/73] rpmsg: fix kconfig dependencies for VIRTIO Greg Kroah-Hartman
2013-05-09 22:24 ` [ 08/73] remoteproc: " Greg Kroah-Hartman
2013-05-09 22:24 ` [ 09/73] hugetlbfs: fix mmap failure in unaligned size request Greg Kroah-Hartman
2013-05-09 22:25 ` [ 10/73] iommu/amd: Properly initialize irq-table lock Greg Kroah-Hartman
2013-05-09 22:25 ` [ 11/73] menuconfig: Fix memory leak introduced by jump keys feature Greg Kroah-Hartman
2013-05-09 22:25 ` [ 12/73] net/eth/ibmveth: Fixup retrieval of MAC address Greg Kroah-Hartman
2013-05-09 22:25 ` [ 13/73] perf/x86/intel: Add support for IvyBridge model 58 Uncore Greg Kroah-Hartman
2013-05-09 22:25 ` [ 14/73] perf/x86/intel: Fix unintended variable name reuse Greg Kroah-Hartman
2013-05-09 22:25 ` [ 15/73] perf/x86: Blacklist all MEM_*_RETIRED events for Ivy Bridge Greg Kroah-Hartman
2013-05-09 22:25 ` [ 16/73] perf/x86/intel/lbr: Fix LBR filter Greg Kroah-Hartman
2013-05-09 22:25 ` [ 17/73] perf/x86/intel/lbr: Demand proper privileges for PERF_SAMPLE_BRANCH_KERNEL Greg Kroah-Hartman
2013-05-09 22:25 ` [ 18/73] ipvs: ip_vs_sip_fill_param() BUG: bad check of return value Greg Kroah-Hartman
2013-05-09 22:25 ` [ 19/73] ext4: add check for inodes_count overflow in new resize ioctl Greg Kroah-Hartman
2013-05-09 22:25 ` [ 20/73] MODSIGN: do not send garbage to stderr when enabling modules signature Greg Kroah-Hartman
2013-05-09 22:25 ` [ 21/73] r8169: fix 8168evl frame padding Greg Kroah-Hartman
2013-05-09 22:25 ` [ 22/73] RDMA/cxgb4: Fix SQ allocation when on-chip SQ is disabled Greg Kroah-Hartman
2013-05-09 22:25 ` [ 23/73] arm64: Ignore the write ESR flag on cache maintenance faults Greg Kroah-Hartman
2013-05-09 22:25 ` [ 24/73] blkcg: fix "scheduling while atomic" in blk_queue_bypass_start Greg Kroah-Hartman
2013-05-09 22:25 ` [ 25/73] block: fix max discard sectors limit Greg Kroah-Hartman
2013-05-09 22:25 ` [ 26/73] drm/cirrus: deal with bo reserve fail in dirty update path Greg Kroah-Hartman
2013-05-09 22:25 ` [ 27/73] drm/mgag200: " Greg Kroah-Hartman
2013-05-09 22:25 ` [ 28/73] drm/gma500: fix backlight hotkeys behaviour on netbooks Greg Kroah-Hartman
2013-05-09 22:25 ` [ 29/73] drm: prime: fix refcounting on the dmabuf import error path Greg Kroah-Hartman
2013-05-09 22:25 ` Greg Kroah-Hartman [this message]
2013-05-09 22:25 ` [ 31/73] drm/ast: deal with bo reserve fail in dirty update path Greg Kroah-Hartman
2013-05-09 22:25 ` [ 32/73] drm/i915: Fix sdvo connector get_hw_state function Greg Kroah-Hartman
2013-05-09 22:25 ` [ 33/73] drm/i915: Add no-lvds quirk for Fujitsu Esprimo Q900 Greg Kroah-Hartman
2013-05-09 22:25 ` [ 34/73] drm/i915: Fix SDVO connector and encoder get_hw_state functions Greg Kroah-Hartman
2013-05-09 22:25 ` [ 35/73] drm/i915: Workaround incoherence between fences and LLC across multiple CPUs Greg Kroah-Hartman
2013-05-09 22:25 ` [ 36/73] drm/i915: Use MLC (l3$) for context objects Greg Kroah-Hartman
2013-05-09 22:25 ` [ 37/73] drm/i915: set CPT FDI RX polarity bits based on VBT Greg Kroah-Hartman
2013-05-09 22:25 ` [ 38/73] drm/i915: dont check inconsistent modeset state when force-restoring Greg Kroah-Hartman
2013-05-09 22:25 ` [ 39/73] drm/i915: ensure single initialization and cleanup of backlight device Greg Kroah-Hartman
2013-05-09 22:25 ` [ 40/73] drm/i915: dont intel_crt_init on any ULT machines Greg Kroah-Hartman
2013-05-09 22:25 ` [ 41/73] drm/i915: Fixup Oops in the pipe config computation Greg Kroah-Hartman
2013-05-09 22:25 ` [ 42/73] drm/i915: Fall back to bit banging mode for DVO transmitter detection Greg Kroah-Hartman
2013-05-09 22:25 ` [ 43/73] drm/i915: correct the calculation of first_pd_entry_in_global_pt Greg Kroah-Hartman
2013-05-09 22:25 ` [ 44/73] drm/radeon: dont use get_engine_clock() on APUs Greg Kroah-Hartman
2013-05-09 22:25 ` [ 45/73] drm/radeon: use frac fb div on RS780/RS880 Greg Kroah-Hartman
2013-05-09 22:25 ` [ 46/73] drm/radeon: fix typo in rv515_mc_resume() Greg Kroah-Hartman
2013-05-09 22:25 ` [ 47/73] drm/radeon/dce6: add missing display reg for tiling setup Greg Kroah-Hartman
2013-05-09 22:25 ` [ 48/73] drm/radeon: update wait_for_vblank for r5xx-r7xx Greg Kroah-Hartman
2013-05-09 22:25 ` [ 49/73] drm/radeon: update wait_for_vblank for evergreen+ Greg Kroah-Hartman
2013-05-09 22:25 ` [ 50/73] drm/radeon: properly lock disp in mc_stop/resume " Greg Kroah-Hartman
2013-05-09 22:25 ` [ 51/73] drm/radeon: properly lock disp in mc_stop/resume for r5xx-r7xx Greg Kroah-Hartman
2013-05-09 22:25 ` [ 52/73] drm/radeon: update wait_for_vblank for r1xx-r4xx Greg Kroah-Hartman
2013-05-09 22:25 ` [ 53/73] drm/radeon: disable the crtcs in mc_stop (evergreen+) (v2) Greg Kroah-Hartman
2013-05-09 22:25 ` [ 54/73] drm/radeon: add some new SI PCI ids Greg Kroah-Hartman
2013-05-09 22:25 ` [ 55/73] drm/radeon/evergreen+: dont enable HPD interrupts on eDP/LVDS Greg Kroah-Hartman
2013-05-09 22:25 ` [ 56/73] drm/radeon: cleanup properly if mmio mapping fails Greg Kroah-Hartman
2013-05-09 22:25 ` [ 57/73] drm/radeon: fix hdmi mode enable on RS600/RS690/RS740 Greg Kroah-Hartman
2013-05-09 22:25 ` [ 58/73] drm/radeon: fix typo in si_select_se_sh() Greg Kroah-Hartman
2013-05-09 22:25 ` [ 59/73] drm/radeon: Always flush the VM Greg Kroah-Hartman
2013-05-09 22:25 ` [ 60/73] drm/radeon: disable the crtcs in mc_stop (r5xx-r7xx) (v2) Greg Kroah-Hartman
2013-05-09 22:25 ` [ 61/73] drm/radeon: fix endian bugs in atom_allocate_fb_scratch() Greg Kroah-Hartman
2013-05-09 22:25 ` [ 62/73] drm/radeon: fix possible segfault when parsing pm tables Greg Kroah-Hartman
2013-05-09 22:25 ` [ 63/73] drm/radeon: add new richland pci ids Greg Kroah-Hartman
2013-05-09 22:25 ` [ 64/73] drm/radeon: fix handling of v6 power tables Greg Kroah-Hartman
2013-05-09 22:25 ` [ 65/73] drm/tilcdc: Fix an incorrect condition Greg Kroah-Hartman
2013-05-09 22:25 ` [ 66/73] tracing: Fix ftrace_dump() Greg Kroah-Hartman
2013-05-09 22:25 ` [ 67/73] Btrfs: compare relevant parts of delayed tree refs Greg Kroah-Hartman
2013-05-09 22:25 ` [ 68/73] Btrfs: fix extent logging with O_DIRECT into prealloc Greg Kroah-Hartman
2013-05-09 22:25 ` [ 69/73] EDAC: Dont give write permission to read-only files Greg Kroah-Hartman
2013-05-09 22:26 ` [ 70/73] PCI: Delay final fixups until resources are assigned Greg Kroah-Hartman
2013-05-09 22:26 ` [ 71/73] qmi_wwan/cdc_ether: add device IDs for Dell 5804 (Novatel E371) WWAN card Greg Kroah-Hartman
2013-05-09 22:26 ` [ 72/73] NFSv4.x: Fix handling of partially delegated locks Greg Kroah-Hartman
2013-05-09 22:26 ` [ 73/73] kernel/audit_tree.c: tree will leak memory when failure occurs in audit_trim_trees() Greg Kroah-Hartman
2013-05-10 15:23 ` [ 00/73] 3.9.2-stable review Shuah Khan
2013-05-10 15:28 ` Greg Kroah-Hartman
2013-05-11 5:26 ` Satoru Takeuchi
2013-05-11 13:53 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130509222529.534649073@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=airlied@redhat.com \
--cc=daniel.vetter@ffwll.ch \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox