From patchwork Thu Aug 29 14:29:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_K=C3=B6nig?= X-Patchwork-Id: 11121847 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 75A0014E5 for ; Thu, 29 Aug 2019 16:16:30 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5D9FD21874 for ; Thu, 29 Aug 2019 16:16:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5D9FD21874 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 431A76E0D5; Thu, 29 Aug 2019 16:16:28 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2DFAB6E10B; Thu, 29 Aug 2019 14:29:22 +0000 (UTC) Received: by mail-wr1-x443.google.com with SMTP id c3so3659581wrd.7; Thu, 29 Aug 2019 07:29:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZzOxEmWrlpWLkJKzR6m7M662G9ObzfXyzQYji+wuxQ8=; b=t1yC50J8ykUuN+XWG26nld+SooPqjXvq/PHqDzVlC09VUsE4vvrHN5H1UZFrsJLbyH MCuq2QYgUWS17hrAiW9KgEFlVBxA4JZYrnUO9rdT7P5FFaRe1s2+HEPOWpkcebzV8Pno u7K4mVs12/K24zBr7Hz18ZvR+cjtszl9WxQ/c7YNt49rQBD9wM6Op93dkxZck2UuuqwX Sn2vEmAtDY55yFdzO2bPU2PhrQ2HSb7NC2ByEzomCL3DROnSt1v0MqPt4yepW5W7/O4R mCOjtqV+M/YzutOaDBtjM2Tx/bSdqLrZxXemtv8p/AovCf8RIGwoI2h6xce7ds7vCDBH C4ug== X-Gm-Message-State: APjAAAWCsDq0PJvTvJnLjFv659Fnla6w7roxtO9tNqH2Hah1rLkYQVYN 9OJlQBZiP0NHNCAKTg/C5g4= X-Google-Smtp-Source: APXvYqzsXyvTtkcvt1CZbpIKEV1RoHlIJWXYGy8P29L/68cg11pTSGkyi03i+0NcRqZdlezcrXVEmA== X-Received: by 2002:adf:82cd:: with SMTP id 71mr11266080wrc.265.1567088960757; Thu, 29 Aug 2019 07:29:20 -0700 (PDT) Received: from abel.fritz.box ([2a02:908:1252:fb60:d57:5a0b:4833:fc9f]) by smtp.gmail.com with ESMTPSA id w13sm6188214wre.44.2019.08.29.07.29.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Aug 2019 07:29:20 -0700 (PDT) From: " =?utf-8?q?Christian_K=C3=B6nig?= " X-Google-Original-From: =?utf-8?q?Christian_K=C3=B6nig?= To: daniel@ffwll.ch, dri-devel@lists.freedesktop.org, sumit.semwal@linaro.org, linaro-mm-sig@lists.linaro.org, linux-media@vger.kernel.org, intel-gfx@lists.freedesktop.org Date: Thu, 29 Aug 2019 16:29:14 +0200 Message-Id: <20190829142917.13058-2-christian.koenig@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190829142917.13058-1-christian.koenig@amd.com> References: <20190829142917.13058-1-christian.koenig@amd.com> MIME-Version: 1.0 X-Mailman-Approved-At: Thu, 29 Aug 2019 16:16:26 +0000 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=ZzOxEmWrlpWLkJKzR6m7M662G9ObzfXyzQYji+wuxQ8=; b=r2MEk5kSlTLEoE7bc+KRz0hBxEpb6lQhgWKAQaHyHnuGDaGA7/fjFGxuPUvVzCLvHO yr9JEO7LhW5DSrdNxki6aW2E2fuyJ87VJ6Wb2saRPDIW0l8C1JcNb/Xn5uIN7BcXq4Hj /EbiVuMX2wiMpb1p6fqrdIXdC1v9VPb5IH1cBk4AY75d6zxILYvOr5/MdvQkexFjq7ZD c5GtMjsGsvfg1RGwu/UTCba4+aqCl2kY+0veb1ulKDw3xZGVQFAgIHZdXq2P104Qxm77 jpXkL6MINLvl4mX4ALHbG1+QahsCvNah+EKnE59mew9abbVVH8YW231qdOSAKhIkXmyr khmQ== Subject: [Intel-gfx] [PATCH 1/4] dma-buf: change DMA-buf locking convention X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" This patch is a stripped down version of the locking changes necessary to support dynamic DMA-buf handling. For compatibility we cache the DMA-buf mapping as soon as exporter/importer disagree on the dynamic handling. Signed-off-by: Christian König --- drivers/dma-buf/dma-buf.c | 90 ++++++++++++++++++++++++++++++++++++--- include/linux/dma-buf.h | 51 +++++++++++++++++++++- 2 files changed, 133 insertions(+), 8 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 433d91d710e4..65052d52602b 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) return ERR_PTR(-EINVAL); } + if (WARN_ON(exp_info->ops->cache_sgt_mapping && + exp_info->ops->dynamic_mapping)) + return ERR_PTR(-EINVAL); + if (!try_module_get(exp_info->owner)) return ERR_PTR(-ENOENT); @@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf) EXPORT_SYMBOL_GPL(dma_buf_put); /** - * dma_buf_attach - Add the device to dma_buf's attachments list; optionally, + * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list; optionally, * calls attach() of dma_buf_ops to allow device-specific attach functionality - * @dmabuf: [in] buffer to attach device to. - * @dev: [in] device to be attached. + * @dmabuf: [in] buffer to attach device to. + * @dev: [in] device to be attached. + * @dynamic_mapping: [in] calling convention for map/unmap * * Returns struct dma_buf_attachment pointer for this attachment. Attachments * must be cleaned up by calling dma_buf_detach(). @@ -662,8 +667,9 @@ EXPORT_SYMBOL_GPL(dma_buf_put); * accessible to @dev, and cannot be moved to a more suitable place. This is * indicated with the error code -EBUSY. */ -struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, - struct device *dev) +struct dma_buf_attachment * +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, + bool dynamic_mapping) { struct dma_buf_attachment *attach; int ret; @@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, attach->dev = dev; attach->dmabuf = dmabuf; + attach->dynamic_mapping = dynamic_mapping; mutex_lock(&dmabuf->lock); @@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, if (ret) goto err_attach; } + dma_resv_lock(dmabuf->resv, NULL); list_add(&attach->node, &dmabuf->attachments); + dma_resv_unlock(dmabuf->resv); mutex_unlock(&dmabuf->lock); + /* When either the importer or the exporter can't handle dynamic + * mappings we cache the mapping here to avoid issues with the + * reservation object lock. + */ + if (dma_buf_attachment_is_dynamic(attach) != + dma_buf_is_dynamic(dmabuf)) { + struct sg_table *sgt; + + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_lock(attach->dmabuf->resv, NULL); + + sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL); + if (!sgt) + sgt = ERR_PTR(-ENOMEM); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_unlock; + } + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_unlock(attach->dmabuf->resv); + attach->sgt = sgt; + attach->dir = DMA_BIDIRECTIONAL; + } + return attach; err_attach: kfree(attach); mutex_unlock(&dmabuf->lock); return ERR_PTR(ret); + +err_unlock: + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_unlock(attach->dmabuf->resv); + + dma_buf_detach(dmabuf, attach); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach); + +/** + * dma_buf_attach - Wrapper for dma_buf_dynamic_attach + * @dmabuf: [in] buffer to attach device to. + * @dev: [in] device to be attached. + * + * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static + * mapping. + */ +struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, + struct device *dev) +{ + return dma_buf_dynamic_attach(dmabuf, dev, false); } EXPORT_SYMBOL_GPL(dma_buf_attach); @@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) if (WARN_ON(!dmabuf || !attach)) return; - if (attach->sgt) + if (attach->sgt) { + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_lock(attach->dmabuf->resv, NULL); + dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir); + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_unlock(attach->dmabuf->resv); + } + mutex_lock(&dmabuf->lock); + dma_resv_lock(dmabuf->resv, NULL); list_del(&attach->node); + dma_resv_unlock(dmabuf->resv); if (dmabuf->ops->detach) dmabuf->ops->detach(dmabuf, attach); @@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, if (WARN_ON(!attach || !attach->dmabuf)) return ERR_PTR(-EINVAL); + if (dma_buf_attachment_is_dynamic(attach)) + dma_resv_assert_held(attach->dmabuf->resv); + if (attach->sgt) { /* * Two mappings with different directions for the same @@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, return attach->sgt; } + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_assert_held(attach->dmabuf->resv); + sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); if (!sg_table) sg_table = ERR_PTR(-ENOMEM); @@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, if (WARN_ON(!attach || !attach->dmabuf || !sg_table)) return; + if (dma_buf_attachment_is_dynamic(attach)) + dma_resv_assert_held(attach->dmabuf->resv); + if (attach->sgt == sg_table) return; + if (dma_buf_is_dynamic(attach->dmabuf)) + dma_resv_assert_held(attach->dmabuf->resv); + attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction); } EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); @@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) seq_puts(s, "\tAttached Devices:\n"); attach_count = 0; + dma_resv_lock(buf_obj->resv, NULL); list_for_each_entry(attach_obj, &buf_obj->attachments, node) { seq_printf(s, "\t%s\n", dev_name(attach_obj->dev)); attach_count++; } + dma_resv_unlock(buf_obj->resv); seq_printf(s, "Total %d devices attached\n\n", attach_count); diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index ec212cb27fdc..a8f8b2b812fd 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -42,6 +42,17 @@ struct dma_buf_ops { */ bool cache_sgt_mapping; + /** + * @dynamic_mapping: + * + * If true the framework makes sure that the map/unmap_dma_buf + * callbacks are always called with the dma_resv object locked. + * + * If false the framework makes ure that the map/unmap_dma_buf + * callbacks are always called without the dma_resv object locked. + */ + bool dynamic_mapping; + /** * @attach: * @@ -109,6 +120,9 @@ struct dma_buf_ops { * any other kind of sharing that the exporter might wish to make * available to buffer-users. * + * This is always called with the dmabuf->resv object locked when + * the dynamic_mapping flag is true. + * * Returns: * * A &sg_table scatter list of or the backing storage of the DMA buffer, @@ -327,6 +341,8 @@ struct dma_buf { * @sgt: cached mapping. * @dir: direction of cached mapping. * @priv: exporter specific attachment data. + * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the + * dma_resv lock held. * * This structure holds the attachment information between the dma_buf buffer * and its user device(s). The list contains one attachment struct per device @@ -343,6 +359,7 @@ struct dma_buf_attachment { struct list_head node; struct sg_table *sgt; enum dma_data_direction dir; + bool dynamic_mapping; void *priv; }; @@ -394,10 +411,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf) get_file(dmabuf->file); } +/** + * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings. + * @dmabuf: the DMA-buf to check + * + * Returns true if a DMA-buf exporter wants to be called with the dma_resv + * locked, false if it doesn't wants to be called with the lock held. + */ +static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf) +{ + return dmabuf->ops->dynamic_mapping; +} + +/** + * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic + * mappinsg + * @attach: the DMA-buf attachment to check + * + * Returns true if a DMA-buf importer wants to call the map/unmap functions with + * the dma_resv lock held. + */ +static inline bool +dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach) +{ + return attach->dynamic_mapping; +} + struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, - struct device *dev); + struct device *dev); +struct dma_buf_attachment * +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, + bool dynamic_mapping); void dma_buf_detach(struct dma_buf *dmabuf, - struct dma_buf_attachment *dmabuf_attach); + struct dma_buf_attachment *attach); struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info); @@ -409,6 +455,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *, enum dma_data_direction); void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *, enum dma_data_direction); +void dma_buf_move_notify(struct dma_buf *dma_buf); int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction dir); int dma_buf_end_cpu_access(struct dma_buf *dma_buf,