mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Zhentao Guo" <zhentao.guo@amlogic.com>
Cc: robh@kernel.org, media-ci@linuxtv.org,
	devicetree@vger.kernel.org, neil.armstrong@linaro.org,
	conor+dt@kernel.org, linux-amlogic@lists.infradead.org
Subject: Re: [PATCH v10 4/6] decoder: Add V4L2 stateless H.264 decoder driver
Date: Thu, 24 Sep 2026 08:16:01 +0000	[thread overview]
Message-ID: <20260924081602.559A31F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260924-b4-s4-vdec-upstream-v10-4-1289303a58a4@amlogic.com>

Thank you for your contribution! Sashiko AI review found 20 potential issue(s) to consider:
- [Critical] media: amlogic: arbitrary physical memory read via unvalidated first_mb_in_slice
- [Critical] media: amlogic: heap buffer overflow in reference list reordering
- [High] media: amlogic: soft lockup via atomic busy-wait in aml_stop_vdec_hw()
- [High] media: amlogic: WARN_ON due to double completion of V4L2 control requests
- [High] media: amlogic: memory leak of h264 context and DMA buffers on STREAMON
- [High] media: amlogic: shifting hardware RefPicList indices on invalid reference
- [High] media: amlogic: incorrect base address for collocated buffers due to 8x8 shift
- [High] media: amlogic: VIFIFO write pointer programmed beyond ring buffer bounds
- [High] media: amlogic: infinite poll timeout deadlocks the threaded IRQ handler
- [High] media: amlogic: out-of-bounds DMA write due to undersized buffers for interlaced
- [High] media: amlogic: UAF when VIDIOC_STREAMOFF frees context concurrently
- [High] media: amlogic: OOB DMA write of collocated MVs during dynamic resolution change
- [High] media: amlogic: UAF of M2M device and devm resources when fd outlives remove
- [High] media: amlogic: threaded IRQ accesses powered-off registers during remove
- [High] media: amlogic: context cleanup unconditionally resets shared hardware
- [High] media: amlogic: early device registration exposes unpowered hardware to userspace
- [High] media: amlogic: missing checks on clock and power domain enablement
- [Medium] media: amlogic: allocation failure for large firmware using kzalloc
- [Medium] media: amlogic: signed integer overflow in collocated buffer bitmask
- [Low] media: amlogic: out-of-bounds read of reorder_cmd array due to off-by-one check
--

commit d745d294471b0d176edba67b04bee8a0c6b95c04
Author: Zhentao Guo <zhentao.guo@amlogic.com>

decoder: Add V4L2 stateless H.264 decoder driver

This commit adds initial support for the v4l2 stateless video decoder driver
on the Amlogic S4 (S805X2) platform, supporting 8-bit H.264 progressive 
bitstream decoding.

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec.c b/drivers/media/platform/amlogic/vdec/aml_vdec.c
> --- a/drivers/media/platform/amlogic/vdec/aml_vdec.c
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec.c
[ ... ]
> @@ m2mops_vdec_device_run @@
>  	if (src_req)
>  		v4l2_ctrl_request_complete(src_req, &ctx->ctrl_handler);
>  	if (ret < 0 || ctx->curr_frm_err_flag)
>  		goto err_cancel_job;
>  	v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx,
>  					 VB2_BUF_STATE_DONE);
[ ... ]
> @@ vb2ops_vdec_buf_request_complete @@
>  static void vb2ops_vdec_buf_request_complete(struct vb2_buffer *vb)
>  {
>  	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
>  
>  	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_handler);
>  }

[Severity: High]
Will this sequence cause a double completion of v4l2 control requests? 

Since m2mops_vdec_device_run() manually calls v4l2_ctrl_request_complete() 
for the source request and then marks the buffer done, the videobuf2 core 
automatically invokes vb2ops_vdec_buf_request_complete(). This secondary 
callback invokes v4l2_ctrl_request_complete() again on the same request, 
which triggers a warn_on() in the media request core.

[ ... ]
> @@ vb2ops_vdec_start_streaming @@
>  	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>  		struct vb2_v4l2_buffer *src_buf;
>  
>  		if (aml_vdec_init_dec_inst(ctx) < 0) {
>  			while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
[ ... ]
> @@ vb2ops_vdec_stop_streaming @@
>  	if (!ctx->is_output_streamon && !ctx->is_cap_streamon)
>  		aml_vdec_release_instance(ctx);

[Severity: High]
Could this leak the h264 context and dma buffers on stream toggle?

Calling vidioc_streamon for the output queue triggers 
vb2ops_vdec_start_streaming(), which blindly allocates a new context via 
aml_h264_init(). If a user calls vidioc_streamoff on the output queue while 
the capture queue remains active, vb2ops_vdec_stop_streaming() skips freeing 
the context because both queues are not stopped. A subsequent streamon on 
the output queue will allocate a new context, irreversibly dropping the 
pointers to the old context and its dma allocations.

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
> --- a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
[ ... ]
> @@ fops_vcodec_release @@
>  static int fops_vcodec_release(struct file *file)
>  {
>  	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(file);
>  
>  	v4l2_m2m_ctx_release(ctx->m2m_ctx);
[ ... ]
> @@ aml_vdec_drv_remove @@
>  	vdec_disable(dev->dec_hw);
>  	media_device_unregister(&dev->mdev);
>  	v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
>  	video_unregister_device(dev->vfd);
>  	media_device_cleanup(&dev->mdev);
>  
>  	v4l2_m2m_release(dev->m2m_dev_dec);
>  	dev->pvdec_data->destroy_hw_resource(dev);

[Severity: High]
Can this lead to a use-after-free if the file descriptor outlives the 
device removal? 

In aml_vdec_drv_remove(), v4l2_m2m_release() explicitly frees the m2m device.
Shortly after, the devm infrastructure frees the aml_vdec_dev structure. 
Because video_unregister_device() does not forcibly close open file 
descriptors, an open file descriptor closed later triggers 
fops_vcodec_release(), which accesses the manually freed m2m_dev and the 
devm-freed ctx->dev.

[Severity: High]
Does this expose unpowered hardware to userspace during registration and 
removal?

In aml_vdec_drv_probe(), video_register_device() exposes the video node 
to userspace before vdec_enable() powers on the hardware domains. Userspace 
could open the device and attempt to start jobs. 

Similarly, in aml_vdec_drv_remove(), vdec_disable() shuts down hardware 
clocks before video_unregister_device() and v4l2_m2m_release() safely 
cancel ongoing m2m jobs. Accessing unclocked or unpowered mmio registers 
often results in a synchronous external abort.

[Severity: High]
Could the threaded irq handler execute and access unpowered registers here?

The hardware is shut down via vdec_disable() before the interrupt requested 
via devm_request_threaded_irq() is disabled and synchronized. If an 
interrupt fires just before vdec_disable(), the threaded isr is scheduled. 
The running h264_threaded_isr_func() will unconditionally read from DOS_BUS 
registers like DPB_STATUS_REG, triggering a synchronous external abort.

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
> --- a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
[ ... ]
> @@ aml_stop_vdec_hw @@
>  	ret = read_poll_timeout_atomic(read_dos_reg, reg_val,
>  				       !(reg_val & 0x8000),
>  				       10, 100000, true,
>  				       hw, IMEM_DMA_CTRL);
>  
>  	ret = read_poll_timeout_atomic(read_dos_reg, reg_val,
>  				       !(reg_val & 0x8000),
>  				       10, 100000, true,
>  				       hw, LMEM_DMA_CTRL);
>  
>  	ret = read_poll_timeout_atomic(read_dos_reg, reg_val,
>  				       !(reg_val & 0xfff),
>  				       10, 300000, true,
>  				       hw, WRRSP_LMEM);

[Severity: High]
Does this stall the cpu for hundreds of milliseconds?

The atomic variants of read_poll_timeout internally loop with udelay(), 
forcing the cpu to busy-wait continuously. Waiting up to 300ms atomically 
is highly likely to trigger rcu stalls and the soft lockup watchdog. 
Since the callers such as aml_h264_exit() execute in sleepable contexts, 
the non-atomic read_poll_timeout() should be used instead.

[ ... ]
> @@ pm_vdec_power_domain_power_on @@
>  	if (gate_node) {
>  		clk_prepare_enable(gate_node->clk);
[ ... ]
>  	if (dev) {
>  		pm_runtime_get_sync(dev);

[Severity: High]
Are the return values for clock and power domain enablement intentionally 
ignored here?

If these calls fail to enable the hardware resources, proceeding to access 
mmio registers in dos_local_config() will result in a synchronous external 
abort, crashing the system.

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_tee_fw.c b/drivers/media/platform/amlogic/vdec/aml_vdec_tee_fw.c
> --- a/drivers/media/platform/amlogic/vdec/aml_vdec_tee_fw.c
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_tee_fw.c
[ ... ]
> @@ get_firmware @@
>  	/* get rid of the first 32K bytes plaintext */
>  	*size = fw->size - UCODE_HEADER_SIZE;
>  	buf = kzalloc(*size, GFP_KERNEL);
>  	if (!buf) {

[Severity: Medium]
Will this kzalloc() succeed for large video firmware blobs on a fragmented 
system? 

Video firmware is typically large, and kzalloc() requires physically 
contiguous pages. Since this buffer is only used to stage data copying 
into tee shared memory in chunks, physical contiguity seems unnecessary. 
Using vmalloc() or kvzalloc() might be more reliable.

> diff --git a/drivers/media/platform/amlogic/vdec/h264.c b/drivers/media/platform/amlogic/vdec/h264.c
> --- a/drivers/media/platform/amlogic/vdec/h264.c
> +++ b/drivers/media/platform/amlogic/vdec/h264.c
[ ... ]
> @@ h264_prepare_input @@
>  	regmap_write(hw->map[DOS_BUS], VLD_MEM_VIFIFO_RP,
>  		     round_down(src_dma, VDEC_FIFO_ALIGN));
>  	dummy = payload_size + VLD_PADDING_SIZE;
>  	regmap_write(hw->map[DOS_BUS], VLD_MEM_VIFIFO_WP,
>  		     round_down((src_dma + dummy), VDEC_FIFO_ALIGN));

[Severity: High]
Can this ring buffer write pointer exceed the defined boundaries?

The hardware bitstream ring buffer is configured with START_PTR at the start 
of the dma buffer and END_PTR strictly at the end of the payload. 
Programming WP past END_PTR causes the hardware to attempt an out-of-bounds 
physical memory read. Also, because the read pointer mathematically wraps 
at END_PTR, it will never equal the out-of-bounds WP, causing the hardware 
to believe the fifo is infinitely full and spin endlessly.

[ ... ]
> @@ config_sps_params @@
>  	h264_ctx->frame_width = (sps->pic_width_in_mbs_minus1 + 1) << 4;
>  	h264_ctx->frame_height = (sps->pic_height_in_map_units_minus1 + 1) << 4;

[Severity: High]
Is there a risk of undersized buffer allocations for interlaced streams?

The driver computes frame_height directly from pic_height_in_map_units_minus1 
without checking the frame_mbs_only_flag. For interlaced content, this 
specifies half the actual frame height. This results in alloc_colocate_cma() 
allocating a half-sized buffer, causing the hardware to perform an 
out-of-bounds dma write during decoding. Progressive-only drivers typically 
reject streams missing the V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY flag.

[ ... ]
> @@ reorder_short_term @@
>  	memcpy(&ref_list_reordered[*ref_idx_lx], pic_lx, sizeof(struct h264_decode_buf_spec));
>  	dev_dbg(&ctx->dev->plat_dev->dev, "%s : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
>  		*ref_idx_lx, pic_lx, ref_list_reordered[*ref_idx_lx].dpb->pic_num);
>  	*ref_idx_lx = *ref_idx_lx + 1;
[ ... ]
> @@ reorder_long_term @@
>  	memcpy(&ref_list[*ref_idx_lx], pic_lt, sizeof(struct h264_decode_buf_spec));
>  	dev_dbg(&ctx->dev->plat_dev->dev, "%s : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
>  		*ref_idx_lx, pic_lt, ref_list[*ref_idx_lx].dpb->pic_num);
>  	*ref_idx_lx = *ref_idx_lx + 1;
[ ... ]
> @@ reorder_pics @@
>  	pic_num_lx_pred = curr_pic_num;
>  	for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && modification_of_pic_nums_idc[i] != 3; i++) {

[Severity: Critical]
Could this loop overflow the ref_list arrays?

The ref_list arrays in aml_h264_ctx are statically sized to 17 elements. 
However, the loop processes up to REORDERING_COMMAND_MAX_SIZE (33) 
reordering commands. Because there is no bounds check ensuring 
*ref_idx_lx < 17 before the memcpy operations in reorder_short_term and 
reorder_long_term, a crafted bitstream with excessive reorder commands can 
trigger a deterministic out-of-bounds write of h264_decode_buf_spec structs 
into adjacent heap memory.

[ ... ]
> @@ alloc_colocate_cma @@
>  	if (h264_ctx->collated_cma_vaddr)
>  		return 0;
>  
>  	hw = vdec_get_hw(ctx->dev);
>  	if (!hw)
>  		return -1;
>  
>  	/* 96 :col buf size for each mb */
>  	h264_ctx->one_col_buf_size = h264_ctx->mb_total * 96;

[Severity: High]
Does this logic correctly update the collocated buffer size during dynamic 
resolution changes?

When a stream dynamically increases in resolution, h264_ctx->mb_total 
increases. However, the early return in alloc_colocate_cma() prevents 
one_col_buf_size from updating. When the hardware later decodes a larger 
frame, it processes the new mb_total macroblocks but the pointer 
calculations rely on the old size, causing an out-of-bounds dma write 
outside the cma buffer bounds.

[ ... ]
> @@ allocate_colocate_buf @@
>  	for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
>  		if (((h264_ctx->colocated_buf_map >> i) & 0x1) == 0) {
>  			h264_ctx->colocated_buf_map |= (1 << i);
>  			break;
>  		}
>  	}
[ ... ]
> @@ release_colocate_buf @@
>  		} else {
>  			if (((h264_ctx->colocated_buf_map >> index) & 0x1) == 0x1) {
>  				h264_ctx->colocated_buf_map &= (~(1 << index));

[Severity: Medium]
Can shifting by 31 bits trigger signed integer overflow?

The expression (1 << i) uses a signed 32-bit integer. If the 31st 
collocated buffer is accessed, it overflows into the sign bit, resulting 
in undefined behavior. Using 1U << i might be safer.

[ ... ]
> @@ get_modification_cmd @@
>  			i++;
>  
>  			if (i >= REORDERING_COMMAND_MAX_SIZE) {
>  				curr_slice->ref_pic_list_reordering_flag[list] = 0;
>  				break;
>  			};
>  			if (j > REORDER_CMD_MAX) {
>  				curr_slice->ref_pic_list_reordering_flag[list] = 0;
>  				break;
>  			};
>  		} while (val != 3);

[Severity: Low]
Is the loop termination condition correct here?

Checking if (j > REORDER_CMD_MAX) fails to break the loop when j reaches 
the array size (66). In the next iteration, the code reads exactly one 
element past the end of the reorder_cmd array.

[ ... ]
> @@ h264_config_decode_buf @@
>  	for (i = 0; i < h264_ctx->list_size[0]; i++) {
>  		if (!h264_ctx->ref_list0[i].valid)
>  			continue;
>  		canvas_pos = h264_ctx->ref_list0[i].canvas_pos;

[Severity: High]
Does skipping invalid reference entries corrupt the hardware's expected 
index array?

If a reference frame is marked as invalid, using continue skips 
accumulating ref_cfg_once and prevents j from incrementing. This compacts 
the reference list, causing all subsequent valid references to shift into 
earlier slots. Shifting the entries breaks temporal prediction and results 
in severe visual corruption.

[ ... ]
> @@ h264_config_decode_buf @@
>  		colocate_wr_adr = (unsigned int)h264_ctx->collated_cma_addr +
>  		    ((h264_ctx->one_col_buf_size *
>  		      h264_ctx->curr_spec.col_buf_index) >> (use_mode_8x8_flag ? 2 : 0));
>  		if (colocate_adr_offset > h264_ctx->one_col_buf_size ||
[ ... ]
>  			colocate_rd_adr = (unsigned int)h264_ctx->collated_cma_addr +
>  			    ((h264_ctx->one_col_buf_size *
>  			      colocate_pic->col_buf_index) >> (use_mode_8x8_flag
>  							       ? 2 : 0));

[Severity: High]
Is the 8x8 shift applied to the correct part of the offset?

By shifting the entire base address computation instead of just the 
intra-buffer offset, the physical base addresses diverge. If a reference 
frame was written with 8x8 mode but read by a current frame without 8x8 
mode, the hardware will read from mismatched physical memory offsets, 
fetching garbage motion vectors.

[ ... ]
> @@ h264_config_decode_buf @@
>  	read_poll_timeout(read_dos_reg, reg_val,
>  			  !(reg_val & 0x800),
>  			  10, 0, true, hw, H264_CO_MB_RW_CTL);

[Severity: High]
Will a timeout parameter of 0 create an infinite loop?

Using read_poll_timeout with a timeout_us argument of 0 creates an infinite 
loop. If the hardware bit fails to clear, the threaded irq handler will spin 
forever. Because it holds the driver's global hw->ctx_mutex, this will 
permanently deadlock the decoder.

[ ... ]
> @@ h264_config_decode_buf @@
>  	colocate_adr_offset = COL_SIZE_FOR_ONE_MB;
>  	if (use_mode_8x8_flag)
>  		colocate_adr_offset >>= 2;
>  	colocate_adr_offset *= curr_slice->first_mb_in_slice;
[ ... ]
>  		colocate_wr_adr = (unsigned int)h264_ctx->collated_cma_addr +
>  		    ((h264_ctx->one_col_buf_size *
>  		      h264_ctx->curr_spec.col_buf_index) >> (use_mode_8x8_flag ? 2 : 0));
>  		if (colocate_adr_offset > h264_ctx->one_col_buf_size ||
[ ... ]
>  			val  = ((colocate_rd_adr_offset + colocate_rd_adr) >> 3) |
>  				(cur_colocate_ref_type << 29) |
>  				(l10_structure << 30);
>  			regmap_write(hw->map[DOS_BUS], H264_CO_MB_RD_ADDR, val);

[Severity: Critical]
Is it safe to use first_mb_in_slice without validation?

This value is parsed directly from the untrusted h264 bitstream and 
multiplied to compute colocate_rd_adr_offset. While there is a bounds 
check for colocate_rd_adr + one_col_buf_size, there is no validation that 
colocate_rd_adr_offset itself remains within the buffer bounds before 
programming the hardware read address. A malicious bitstream supplying a 
massive first_mb_in_slice could cause arbitrary physical memory reads.

[ ... ]
> @@ aml_h264_exit @@
>  	if (ctx->dos_clk_en)
>  		aml_stop_vdec_hw(dec_hw);
>  
>  	if (h264_ctx->collated_cma_vaddr) {
[ ... ]
>  	kfree(ctx->codec_priv);
>  	ctx->codec_priv = NULL;
>  }
[ ... ]
> @@ aml_h264_dec_run @@
>  		aml_stop_vdec_hw(dec_hw);
>  		synchronize_irq(dec_hw->dec_irq);
>  		h264_release_decode_spec(dec_hw, ctx);
>  	}
>  
>  	h264_ctx->init_flag = 0;
>  	aml_vdec_set_curr_ctx(dec_hw, NULL);

[Severity: High]
Could a concurrent vidioc_streamoff trigger a use-after-free?

If userspace calls vidioc_streamoff, aml_h264_exit() frees ctx->codec_priv. 
However, if aml_h264_dec_run() is actively sleeping on 
wait_event_interruptible_timeout() in the m2m worker thread, the forced 
hardware stop causes the wait to return. The worker thread will immediately 
dereference the freed h264_ctx without any synchronization.

[Severity: High]
Does this teardown sequence unconditionally reset shared hardware?

The aml_vdec_hw block is a global resource shared by all active v4l2 decoder 
instances. During teardown, aml_h264_exit() unconditionally calls 
aml_stop_vdec_hw(dec_hw) which issues soft resets to the shared DOS_BUS 
registers. There is no check ensuring that the tearing-down context actually 
owns the hardware. If another context is actively decoding, resetting the 
hardware underneath it will cause timeouts and state corruption.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260924-b4-s4-vdec-upstream-v10-0-1289303a58a4@amlogic.com?part=4

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  reply	other threads:[~2026-09-24  8:16 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-24  7:55 [PATCH v10 0/6] Add Amlogic stateless H.264 video decoder for S4 Zhentao Guo via B4 Relay
2026-09-24  7:55 ` [PATCH v10 1/6] firmware: meson: sm: video firmware loading via secure monitor Zhentao Guo via B4 Relay
2026-09-24  7:55 ` [PATCH v10 2/6] firmware: meson: sm: Add video firmware loading SMC call Zhentao Guo via B4 Relay
2026-09-24  7:55 ` [PATCH v10 3/6] media: dt-bindings: Add Amlogic V4L2 video decoder Zhentao Guo via B4 Relay
2026-09-24  8:01   ` sashiko-bot
2026-09-24  7:55 ` [PATCH v10 4/6] decoder: Add V4L2 stateless H.264 decoder driver Zhentao Guo via B4 Relay
2026-09-24  8:16   ` sashiko-bot [this message]
2026-09-24  7:55 ` [PATCH v10 5/6] arm64: dts: amlogic: Add video decoder driver support for S4 SOCs Zhentao Guo via B4 Relay
2026-09-24  7:55 ` [PATCH v10 6/6] arm64: defconfig: Enable CONFIG_VIDEO_AMLOGIC_VDEC Zhentao Guo via B4 Relay

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=20260924081602.559A31F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=media-ci@linuxtv.org \
    --cc=neil.armstrong@linaro.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=zhentao.guo@amlogic.com \
    /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®