From: "Diederik de Haas" <diederik@cknow-tech.com>
To: "Karl Mehltretter" <kmehltretter@gmail.com>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>
Cc: "Andrew Morton" <akpm@linux-foundation.org>,
"Jason Gunthorpe" <jgg@nvidia.com>,
"Rob Clark" <rob.clark@oss.qualcomm.com>,
"Jianfeng Liu" <liujianfeng1994@gmail.com>,
"Diederik de Haas" <diederik@cknow-tech.com>,
"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
"Vinod Koul" <vkoul@kernel.org>,
"Bjorn Andersson" <andersson@kernel.org>,
<linux-media@vger.kernel.org>, <dri-devel@lists.freedesktop.org>,
<linaro-mm-sig@lists.linaro.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [RFC PATCH 2/3] dma-buf: add a warn-only mode to DMABUF_DEBUG
Date: Wed, 07 Oct 2026 14:02:31 +0200 [thread overview]
Message-ID: <DLYLA3WQNN3X.3FB9MO8ZWBQ5@cknow-tech.com> (raw)
In-Reply-To: <20261005064133.7305-3-kmehltretter@gmail.com>
Hi,
On Mon Oct 5, 2026 at 8:41 AM CEST, Karl Mehltretter wrote:
> DMABUF_DEBUG hands importers a copy of the exporter's sg_table without
> the struct pages. An importer that uses them then fails, often far from
> the cause and without a message that points at it. Where sg_dma_len()
> is sg->length, the copy cannot hide the length either.
>
> Add DMABUF_DEBUG_WARN. With it the copy keeps the CPU side of the
> exporter's table: page, offset and length of all orig_nents entries,
> and the exporter's nents and orig_nents. A table without a CPU side
> (orig_nents == 0) stays that way. Every entry of the copy is marked
> with a new dma_flags bit, SG_DMA_DMABUF_DEBUG.
>
> sg_page(), sg_nents_for_len() and sg_split() test the bit and print a
> rate limited message with a stack trace. sg_page() is mostly reached
> through DMA and scatterlist helpers, so the trace is what names the
> importer. These CPU-side accesses can continue after the report instead
> of failing because the fields were cleared.
>
> The report is not a WARN(). It does not taint the kernel and does not
> trigger panic_on_warn.
>
> Reads of sg->offset and sg->length that do not go through these
> helpers are not seen. The option adds a test to every sg_page() and
> selects NEED_SG_DMA_FLAGS.
>
> Strict mode remains the default and continues to remove the CPU-side
> fields.
Thanks for this patch set!
I build a 7.3-rc6 based kernel with this patch set included.
And I (ofc) enabled DMABUF_DEBUG and DMABUF_DEBUG_WARN.
I then tested it on my NanoPC-T6 Plus (RK3588 SoC) connected to my 1080p
monitor and also on my NanoPC-T6 LTS (RK3588) connected to my 4K TV (which
is HDMI 2.0, not 2.1, capable).
On both devices I got an identical call trace.
I did get a new (identical) one every time I resized the video window,
ie going from windowed to full-screen and back again.
```sh
[ 1091.981354] rc rc3: two consecutive events of type space
[ 1104.670513] input: EDIFIER e235 (AVRCP) as /devices/virtual/input/input12
[ 1172.090231] devfreq fb000000.gpu: Couldn't update frequency transition information.
[ 1189.403278] devfreq fb000000.gpu: Couldn't update frequency transition information.
[ 1206.309295] input: EDIFIER e235 (AVRCP) as /devices/virtual/input/input13
[ 1268.968696] DMA-BUF: importer used the CPU side of an exporter's sg_table
[ 1268.968710] CPU: 6 UID: 1000 PID: 29025 Comm: sway Not tainted 7.3-rc6+unreleased-arm64-cknow #1 PREEMPTLAZY Debian 7.3~rc6-3
[ 1268.968715] Hardware name: FriendlyElec NanoPC-T6 Plus (DT)
[ 1268.968717] Call trace:
[ 1268.968719] show_stack+0x20/0x38 (C)
[ 1268.968726] dump_stack_lvl+0x60/0x80
[ 1268.968730] sg_dmabuf_cpu_access_warn.part.0+0x24/0x30
[ 1268.968734] sg_dmabuf_cpu_access_warn+0x34/0x38
[ 1268.968739] iommu_map_sg+0xc8/0x1e0
[ 1268.968745] rockchip_gem_iommu_map+0x8c/0x128 [rockchipdrm]
[ 1268.968757] rockchip_gem_prime_import_sg_table+0x58/0x160 [rockchipdrm]
[ 1268.968761] drm_gem_prime_import_dev+0xa8/0x1d0 [drm]
[ 1268.968776] drm_gem_prime_fd_to_handle+0x1a4/0x280 [drm]
[ 1268.968786] drm_prime_fd_to_handle_ioctl+0x40/0x58 [drm]
[ 1268.968796] drm_ioctl_kernel+0xc8/0x140 [drm]
[ 1268.968806] drm_ioctl+0x254/0x558 [drm]
[ 1268.968816] __arm64_sys_ioctl+0xac/0x118
[ 1268.968821] invoke_syscall.constprop.0+0xac/0x110
[ 1268.968825] el0_svc_common.constprop.0+0x40/0xf0
[ 1268.968829] do_el0_svc+0x24/0x40
[ 1268.968832] el0_svc+0x40/0x260
[ 1268.968836] el0t_64_sync_handler+0xa0/0xe8
[ 1268.968838] el0t_64_sync+0x198/0x1a0
[ 1290.531300] sg_dmabuf_cpu_access_warn: 36 callbacks suppressed
[ 1290.531310] DMA-BUF: importer used the CPU side of an exporter's sg_table
[ 1290.531319] CPU: 5 UID: 1000 PID: 29025 Comm: sway Not tainted 7.3-rc6+unreleased-arm64-cknow #1 PREEMPTLAZY Debian 7.3~rc6-3
[ 1290.531323] Hardware name: FriendlyElec NanoPC-T6 Plus (DT)
[ 1290.531325] Call trace:
[ 1290.531327] show_stack+0x20/0x38 (C)
[ 1290.531335] dump_stack_lvl+0x60/0x80
[ 1290.531338] sg_dmabuf_cpu_access_warn.part.0+0x24/0x30
[ 1290.531342] sg_dmabuf_cpu_access_warn+0x34/0x38
[ 1290.531347] iommu_map_sg+0xc8/0x1e0
[ 1290.531352] rockchip_gem_iommu_map+0x8c/0x128 [rockchipdrm]
[ 1290.531364] rockchip_gem_prime_import_sg_table+0x58/0x160 [rockchipdrm]
[ 1290.531368] drm_gem_prime_import_dev+0xa8/0x1d0 [drm]
[ 1290.531384] drm_gem_prime_fd_to_handle+0x1a4/0x280 [drm]
[ 1290.531394] drm_prime_fd_to_handle_ioctl+0x40/0x58 [drm]
[ 1290.531404] drm_ioctl_kernel+0xc8/0x140 [drm]
[ 1290.531414] drm_ioctl+0x254/0x558 [drm]
[ 1290.531424] __arm64_sys_ioctl+0xac/0x118
[ 1290.531429] invoke_syscall.constprop.0+0xac/0x110
[ 1290.531433] el0_svc_common.constprop.0+0x40/0xf0
[ 1290.531437] do_el0_svc+0x24/0x40
[ 1290.531439] el0_svc+0x40/0x260
[ 1290.531444] el0t_64_sync_handler+0xa0/0xe8
[ 1290.531446] el0t_64_sync+0x198/0x1a0
[ 1294.197699] devfreq fb000000.gpu: Couldn't update frequency transition information.
[ 1313.464098] sg_dmabuf_cpu_access_warn: 149 callbacks suppressed
[ 1313.464121] DMA-BUF: importer used the CPU side of an exporter's sg_table
[ 1313.464144] CPU: 2 UID: 1000 PID: 29025 Comm: sway Not tainted 7.3-rc6+unreleased-arm64-cknow #1 PREEMPTLAZY Debian 7.3~rc6-3
[ 1313.464156] Hardware name: FriendlyElec NanoPC-T6 Plus (DT)
[ 1313.464163] Call trace:
[ 1313.464168] show_stack+0x20/0x38 (C)
...
```
Full dmesg output is posted here:
https://paste.sr.ht/~diederik/3d0020b4f3b0e8547397c20d5c10387d88d32341
Hopefully this helps fixing the underlaying issue.
Cheers,
Diederik
> Assisted-by: LLM
> Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
> ---
>
> Notes:
> Tested on v7.3-rc4-70-gfe2ec83746e5 with GCC 15.2.0.
>
> Builds, without warnings:
>
> - x86_64 with DMABUF_DEBUG_WARN=y, full build
> - arm64 defconfig with DMABUF_DEBUG_WARN=y: Image, and the msm and
> rockchip DRM drivers
> - ARM926 (SAM9X75) with DMABUF_DEBUG_WARN=y and without
> NEED_SG_DMA_LENGTH, full build
> - ARM926 with DMABUF_DEBUG=n and without NEED_SG_DMA_FLAGS, full build.
> dma-buf.o and lib/scatterlist.o disassemble as on the base commit,
> except for __LINE__ constants.
> - x86_64 with SG_SPLIT, W=1, the objects touched here: with
> DMABUF_DEBUG_WARN=y, with DMABUF_DEBUG=y alone, and with
> DMABUF_DEBUG=n
>
> Runtime, both in QEMU with local device models, not on hardware.
>
> Zynq with an AXI ADC, IIO DMABUF capture into udmabuf buffers,
> NEED_SG_DMA_LENGTH=y. The IIO dmaengine buffer calls sg_nents_for_len()
> on the attachment's table. With DMABUF_DEBUG=y alone the capture fails:
>
> DMABUF_ENQUEUE failed: Device or resource busy
>
> With DMABUF_DEBUG_WARN=y all 16 blocks arrive with the right data, the
> kernel is not tainted, and the log has one report:
>
> DMA-BUF: importer used the CPU side of an exporter's sg_table
> CPU: 0 UID: 0 PID: 48 Comm: iio-dmabuf Not tainted 7.3.0-rc4+ #2 VOLUNTARY
> Hardware name: Xilinx Zynq Platform
> Call trace:
> unwind_backtrace from show_stack+0x10/0x14
> show_stack from dump_stack_lvl+0x54/0x68
> dump_stack_lvl from sg_nents_for_len+0xd8/0xe4
> sg_nents_for_len from iio_dmaengine_buffer_submit_block+0x4c/0x33c
> iio_dmaengine_buffer_submit_block from iio_dma_buffer_submit_block.part.0+0x5c/0x104
> iio_dma_buffer_submit_block.part.0 from iio_dma_buffer_enqueue_dmabuf+0x68/0xa0
> iio_dma_buffer_enqueue_dmabuf from iio_buffer_chrdev_ioctl+0x520/0x9a4
> iio_buffer_chrdev_ioctl from sys_ioctl+0x460/0x914
> sys_ioctl from ret_fast_syscall+0x0/0x4c
>
> x86_64 with intel-iommu, xHCI and a SUR40, capture into udmabuf
> buffers. This kernel had a one-line test-only change in sur40 that
> makes the vb2 queue use the USB controller's DMA device. There was no
> report during boot. The capture gives one, from sg_page() in
> iommu_dma_map_sg():
>
> DMA-BUF: importer used the CPU side of an exporter's sg_table
> CPU: 0 UID: 0 PID: 9 Comm: kworker/0:0 Not tainted 7.3.0-rc4+ #5 PREEMPT(lazy)
> Workqueue: events_freezable input_dev_poller_work
> Call Trace:
> <TASK>
> dump_stack_lvl+0x4d/0x70
> iommu_dma_map_sg+0x4c0/0x1010
> __dma_map_sg_attrs+0x254/0x3b0
> dma_map_sg_attrs+0xe/0x20
> usb_hcd_map_urb_for_dma+0x7e0/0x1620
> usb_hcd_submit_urb+0x162/0x1af0
> usb_sg_wait+0x17c/0x550
> sur40_poll+0xb3e/0xff0
> input_dev_poller_work+0x54/0x90
> process_one_work+0x692/0xf90
> [...]
>
> The capture did not finish in this setup. The guest stalled in
> xhci_queue_bulk_tx() after the report, so this run only shows the
> report.
>
> The SG_DMA_* defines move up in scatterlist.h because sg_page() needs
> the new one.
>
> drivers/dma-buf/Kconfig | 23 +++++++++++++++++++
> drivers/dma-buf/dma-buf.c | 44 ++++++++++++++++++++++++++++++++++++-
> include/linux/scatterlist.h | 26 +++++++++++++++++++---
> lib/scatterlist.c | 22 +++++++++++++++++++
> lib/sg_split.c | 2 ++
> 5 files changed, 113 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
> index e4f078a326a4..06177465091a 100644
> --- a/drivers/dma-buf/Kconfig
> +++ b/drivers/dma-buf/Kconfig
> @@ -49,6 +49,29 @@ config DMABUF_DEBUG
> exporters. Specifically it validates that importers do not peek at the
> underlying struct page when they import a buffer.
>
> +config DMABUF_DEBUG_WARN
> + bool "Warn instead of hiding the pages from DMA-BUF importers"
> + depends on DMABUF_DEBUG
> + select NEED_SG_DMA_FLAGS
> + help
> + DMABUF_DEBUG normally hands importers a copy of the exporter's
> + sg_table without the struct page pointers, so that an importer which
> + uses them fails early.
> +
> + With this option the copy keeps the pages, offsets and lengths and is
> + only marked. sg_page() and the helpers built on it, sg_nents_for_len()
> + and sg_split() then print a rate limited message with a stack trace
> + when they are used on such a table. The access itself continues
> + instead of failing because the fields were cleared. The message is
> + not a WARN(): it does not taint the kernel or trigger panic_on_warn.
> +
> + Importers that read sg->offset or sg->length directly are not
> + noticed. The option adds a test to every sg_page() call. It selects
> + NEED_SG_DMA_FLAGS, which adds dma_flags and may increase the size of
> + struct scatterlist.
> +
> + If unsure, say N.
> +
> config DMABUF_KUNIT_TEST
> tristate "KUnit tests for DMA-BUF" if !KUNIT_ALL_TESTS
> depends on KUNIT
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index b3d311acb883..bd82b6b7f5ff 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -57,6 +57,7 @@
> struct dma_buf_sg_table_wrapper {
> struct sg_table *original;
> struct sg_table wrapper;
> + unsigned int alloc_nents;
> };
>
> static inline int is_dma_buf_file(struct file *);
> @@ -874,11 +875,42 @@ void dma_buf_put(struct dma_buf *dmabuf)
> }
> EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");
>
> +#ifdef CONFIG_DMABUF_DEBUG_WARN
> +/*
> + * Warn mode: the importer also gets the CPU side of the exporter's table,
> + * marked so that sg_page() and friends can report who uses it.
> + */
> +static void dma_buf_wrap_cpu_side(struct sg_table *to, struct sg_table *from)
> +{
> + struct scatterlist *to_sg, *from_sg;
> + int i;
> +
> + for_each_sgtable_sg(to, to_sg, i)
> + to_sg->dma_flags |= SG_DMA_DMABUF_DEBUG;
> +
> + to_sg = to->sgl;
> + for_each_sgtable_sg(from, from_sg, i) {
> + sg_assign_page(to_sg, sg_page(from_sg));
> + to_sg->offset = from_sg->offset;
> + to_sg->length = from_sg->length;
> + to_sg = sg_next(to_sg);
> + }
> +
> + to->nents = from->nents;
> + to->orig_nents = from->orig_nents;
> +}
> +#else
> +static void dma_buf_wrap_cpu_side(struct sg_table *to, struct sg_table *from)
> +{
> +}
> +#endif
> +
> static int dma_buf_wrap_sg_table(struct sg_table **sg_table)
> {
> struct scatterlist *to_sg, *from_sg;
> struct sg_table *from = *sg_table;
> struct dma_buf_sg_table_wrapper *to;
> + unsigned int nents = from->nents;
> int i, ret;
>
> if (!IS_ENABLED(CONFIG_DMABUF_DEBUG))
> @@ -888,14 +920,21 @@ static int dma_buf_wrap_sg_table(struct sg_table **sg_table)
> * To catch abuse of the underlying struct page by importers copy the
> * sg_table without copying the page_link and give only the copy back to
> * the importer.
> + *
> + * With DMABUF_DEBUG_WARN the copy keeps the CPU side, which can have
> + * more entries than the DMA side.
> */
> to = kzalloc_obj(*to);
> if (!to)
> return -ENOMEM;
>
> - ret = sg_alloc_table(&to->wrapper, from->nents, GFP_KERNEL);
> + if (IS_ENABLED(CONFIG_DMABUF_DEBUG_WARN))
> + nents = max(nents, from->orig_nents);
> +
> + ret = sg_alloc_table(&to->wrapper, nents, GFP_KERNEL);
> if (ret)
> goto free_to;
> + to->alloc_nents = nents;
>
> to_sg = to->wrapper.sgl;
> for_each_sgtable_dma_sg(from, from_sg, i) {
> @@ -910,6 +949,7 @@ static int dma_buf_wrap_sg_table(struct sg_table **sg_table)
> #endif
> to_sg = sg_next(to_sg);
> }
> + dma_buf_wrap_cpu_side(&to->wrapper, from);
>
> to->original = from;
> *sg_table = &to->wrapper;
> @@ -929,6 +969,8 @@ static void dma_buf_unwrap_sg_table(struct sg_table **sg_table)
>
> copy = container_of(*sg_table, typeof(*copy), wrapper);
> *sg_table = copy->original;
> + /* sg_free_table() needs the number of allocated entries */
> + copy->wrapper.orig_nents = copy->alloc_nents;
> sg_free_table(©->wrapper);
> kfree(copy);
> }
> diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
> index 6de1a2434299..5dc8c134ca4c 100644
> --- a/include/linux/scatterlist.h
> +++ b/include/linux/scatterlist.h
> @@ -21,6 +21,13 @@ struct scatterlist {
> #endif
> };
>
> +/* Bits in dma_flags, see below. sg_page() needs SG_DMA_DMABUF_DEBUG. */
> +#ifdef CONFIG_NEED_SG_DMA_FLAGS
> +#define SG_DMA_BUS_ADDRESS (1 << 0)
> +#define SG_DMA_SWIOTLB (1 << 1)
> +#define SG_DMA_DMABUF_DEBUG (1 << 2)
> +#endif
> +
> /*
> * These macros should be used after a dma_map_sg call has been done
> * to get bus addresses of each of the SG entries and their lengths.
> @@ -188,11 +195,27 @@ static inline void sg_set_folio(struct scatterlist *sg, struct folio *folio,
> sg->length = len;
> }
>
> +#ifdef CONFIG_DMABUF_DEBUG_WARN
> +void sg_dmabuf_cpu_access_warn(void);
> +
> +/* Report use of the CPU side of a table that a DMA-BUF importer was given */
> +static inline void sg_dmabuf_cpu_access_check(struct scatterlist *sg)
> +{
> + if (unlikely(sg->dma_flags & SG_DMA_DMABUF_DEBUG))
> + sg_dmabuf_cpu_access_warn();
> +}
> +#else
> +static inline void sg_dmabuf_cpu_access_check(struct scatterlist *sg)
> +{
> +}
> +#endif
> +
> static inline struct page *sg_page(struct scatterlist *sg)
> {
> #ifdef CONFIG_DEBUG_SG
> BUG_ON(sg_is_chain(sg));
> #endif
> + sg_dmabuf_cpu_access_check(sg);
> return (struct page *)((sg)->page_link & ~SG_PAGE_LINK_MASK);
> }
>
> @@ -303,9 +326,6 @@ static inline void sg_unmark_end(struct scatterlist *sg)
> */
> #ifdef CONFIG_NEED_SG_DMA_FLAGS
>
> -#define SG_DMA_BUS_ADDRESS (1 << 0)
> -#define SG_DMA_SWIOTLB (1 << 1)
> -
> /**
> * sg_dma_is_bus_address - Return whether a given segment was marked
> * as a bus address
> diff --git a/lib/scatterlist.c b/lib/scatterlist.c
> index 6ea40d2e6247..55a3697df881 100644
> --- a/lib/scatterlist.c
> +++ b/lib/scatterlist.c
> @@ -12,6 +12,27 @@
> #include <linux/bvec.h>
> #include <linux/uio.h>
> #include <linux/folio_queue.h>
> +#include <linux/printk.h>
> +#include <linux/ratelimit.h>
> +
> +#ifdef CONFIG_DMABUF_DEBUG_WARN
> +/*
> + * Not a WARN(): a wrong importer must not taint the kernel or trigger
> + * panic_on_warn. sg_page() is mostly reached through DMA or scatterlist
> + * helpers, so the stack trace is what identifies the importer.
> + */
> +void sg_dmabuf_cpu_access_warn(void)
> +{
> + static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, 1);
> +
> + if (!__ratelimit(&rs))
> + return;
> +
> + pr_warn("DMA-BUF: importer used the CPU side of an exporter's sg_table\n");
> + dump_stack_lvl(KERN_WARNING);
> +}
> +EXPORT_SYMBOL(sg_dmabuf_cpu_access_warn);
> +#endif
>
> /**
> * sg_nents - return total count of entries in scatterlist
> @@ -54,6 +75,7 @@ int sg_nents_for_len(struct scatterlist *sg, u64 len)
> return 0;
>
> for (nents = 0, total = 0; sg; sg = sg_next(sg)) {
> + sg_dmabuf_cpu_access_check(sg);
> nents++;
> total += sg->length;
> if (total >= len)
> diff --git a/lib/sg_split.c b/lib/sg_split.c
> index 24e8f5e48e63..cbbc7f9a206d 100644
> --- a/lib/sg_split.c
> +++ b/lib/sg_split.c
> @@ -33,6 +33,8 @@ static int sg_calculate_split(struct scatterlist *in, int nents, int nb_splits,
> }
>
> for_each_sg(in, sg, nents, i) {
> + if (!mapped)
> + sg_dmabuf_cpu_access_check(sg);
> sglen = mapped ? sg_dma_len(sg) : sg->length;
> if (skip > sglen) {
> skip -= sglen;
next prev parent reply other threads:[~2026-10-07 12:02 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 6:41 [RFC PATCH 0/3] dma-buf: warn-only mode for DMABUF_DEBUG Karl Mehltretter
2026-10-05 6:41 ` [RFC PATCH 1/3] dma-buf: keep the DMA flags in the DMABUF_DEBUG copy Karl Mehltretter
2026-10-05 6:41 ` [RFC PATCH 2/3] dma-buf: add a warn-only mode to DMABUF_DEBUG Karl Mehltretter
2026-10-07 12:02 ` Diederik de Haas [this message]
2026-10-05 6:41 ` [RFC PATCH 3/3] dma-buf: test the debug scatterlist wrapper Karl Mehltretter
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=DLYLA3WQNN3X.3FB9MO8ZWBQ5@cknow-tech.com \
--to=diederik@cknow-tech.com \
--cc=akpm@linux-foundation.org \
--cc=andersson@kernel.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jgg@nvidia.com \
--cc=kmehltretter@gmail.com \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=liujianfeng1994@gmail.com \
--cc=rob.clark@oss.qualcomm.com \
--cc=sumit.semwal@linaro.org \
--cc=vkoul@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
all inboxes | Powered by JetHome®