From: Paul Cercueil <paul@crapouillou.net> To: Jonathan Cameron <jic23@kernel.org> Cc: "Paul Cercueil" <paul@crapouillou.net>, "Michael Hennerich" <Michael.Hennerich@analog.com>, "Jonathan Corbet" <corbet@lwn.net>, linux-iio@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, "Alexandru Ardelean" <ardeleanalex@gmail.com>, "Christian König" <christian.koenig@amd.com> Subject: [PATCH v2 02/12] iio: buffer-dma: Enable buffer write support Date: Mon, 7 Feb 2022 12:59:23 +0000 [thread overview] Message-ID: <20220207125933.81634-3-paul@crapouillou.net> (raw) In-Reply-To: <20220207125933.81634-1-paul@crapouillou.net> Adding write support to the buffer-dma code is easy - the write() function basically needs to do the exact same thing as the read() function: dequeue a block, read or write the data, enqueue the block when entirely processed. Therefore, the iio_buffer_dma_read() and the new iio_buffer_dma_write() now both call a function iio_buffer_dma_io(), which will perform this task. The .space_available() callback can return the exact same value as the .data_available() callback for input buffers, since in both cases we count the exact same thing (the number of bytes in each available block). Note that we preemptively reset block->bytes_used to the buffer's size in iio_dma_buffer_request_update(), as in the future the iio_dma_buffer_enqueue() function won't reset it. v2: - Fix block->state not being reset in iio_dma_buffer_request_update() for output buffers. - Only update block->bytes_used once and add a comment about why we update it. - Add a comment about why we're setting a different state for output buffers in iio_dma_buffer_request_update() - Remove useless cast to bool (!!) in iio_dma_buffer_io() Signed-off-by: Paul Cercueil <paul@crapouillou.net> Reviewed-by: Alexandru Ardelean <ardeleanalex@gmail.com> --- drivers/iio/buffer/industrialio-buffer-dma.c | 88 ++++++++++++++++---- include/linux/iio/buffer-dma.h | 7 ++ 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 1fc91467d1aa..a9f1b673374f 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -195,6 +195,18 @@ static void _iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) block->state = IIO_BLOCK_STATE_DONE; } +static void iio_dma_buffer_queue_wake(struct iio_dma_buffer_queue *queue) +{ + __poll_t flags; + + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) + flags = EPOLLIN | EPOLLRDNORM; + else + flags = EPOLLOUT | EPOLLWRNORM; + + wake_up_interruptible_poll(&queue->buffer.pollq, flags); +} + /** * iio_dma_buffer_block_done() - Indicate that a block has been completed * @block: The completed block @@ -212,7 +224,7 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) spin_unlock_irqrestore(&queue->list_lock, flags); iio_buffer_block_put_atomic(block); - wake_up_interruptible_poll(&queue->buffer.pollq, EPOLLIN | EPOLLRDNORM); + iio_dma_buffer_queue_wake(queue); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done); @@ -241,7 +253,7 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue, } spin_unlock_irqrestore(&queue->list_lock, flags); - wake_up_interruptible_poll(&queue->buffer.pollq, EPOLLIN | EPOLLRDNORM); + iio_dma_buffer_queue_wake(queue); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort); @@ -335,8 +347,24 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) queue->fileio.blocks[i] = block; } - block->state = IIO_BLOCK_STATE_QUEUED; - list_add_tail(&block->head, &queue->incoming); + /* + * block->bytes_used may have been modified previously, e.g. by + * iio_dma_buffer_block_list_abort(). Reset it here to the + * block's so that iio_dma_buffer_io() will work. + */ + block->bytes_used = block->size; + + /* + * If it's an input buffer, mark the block as queued, and + * iio_dma_buffer_enable() will submit it. Otherwise mark it as + * done, which means it's ready to be dequeued. + */ + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) { + block->state = IIO_BLOCK_STATE_QUEUED; + list_add_tail(&block->head, &queue->incoming); + } else { + block->state = IIO_BLOCK_STATE_DONE; + } } out_unlock: @@ -465,20 +493,12 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( return block; } -/** - * iio_dma_buffer_read() - DMA buffer read callback - * @buffer: Buffer to read form - * @n: Number of bytes to read - * @user_buffer: Userspace buffer to copy the data to - * - * Should be used as the read callback for iio_buffer_access_ops - * struct for DMA buffers. - */ -int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, - char __user *user_buffer) +static int iio_dma_buffer_io(struct iio_buffer *buffer, + size_t n, char __user *user_buffer, bool is_write) { struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); struct iio_dma_buffer_block *block; + void *addr; int ret; if (n < buffer->bytes_per_datum) @@ -501,8 +521,13 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, n = rounddown(n, buffer->bytes_per_datum); if (n > block->bytes_used - queue->fileio.pos) n = block->bytes_used - queue->fileio.pos; + addr = block->vaddr + queue->fileio.pos; - if (copy_to_user(user_buffer, block->vaddr + queue->fileio.pos, n)) { + if (is_write) + ret = copy_from_user(addr, user_buffer, n); + else + ret = copy_to_user(user_buffer, addr, n); + if (ret) { ret = -EFAULT; goto out_unlock; } @@ -521,8 +546,39 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, return ret; } + +/** + * iio_dma_buffer_read() - DMA buffer read callback + * @buffer: Buffer to read form + * @n: Number of bytes to read + * @user_buffer: Userspace buffer to copy the data to + * + * Should be used as the read callback for iio_buffer_access_ops + * struct for DMA buffers. + */ +int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, + char __user *user_buffer) +{ + return iio_dma_buffer_io(buffer, n, user_buffer, false); +} EXPORT_SYMBOL_GPL(iio_dma_buffer_read); +/** + * iio_dma_buffer_write() - DMA buffer write callback + * @buffer: Buffer to read form + * @n: Number of bytes to read + * @user_buffer: Userspace buffer to copy the data from + * + * Should be used as the write callback for iio_buffer_access_ops + * struct for DMA buffers. + */ +int iio_dma_buffer_write(struct iio_buffer *buffer, size_t n, + const char __user *user_buffer) +{ + return iio_dma_buffer_io(buffer, n, (__force char *)user_buffer, true); +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_write); + /** * iio_dma_buffer_data_available() - DMA buffer data_available callback * @buf: Buffer to check for data availability diff --git a/include/linux/iio/buffer-dma.h b/include/linux/iio/buffer-dma.h index 18d3702fa95d..490b93f76fa8 100644 --- a/include/linux/iio/buffer-dma.h +++ b/include/linux/iio/buffer-dma.h @@ -132,6 +132,8 @@ int iio_dma_buffer_disable(struct iio_buffer *buffer, struct iio_dev *indio_dev); int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, char __user *user_buffer); +int iio_dma_buffer_write(struct iio_buffer *buffer, size_t n, + const char __user *user_buffer); size_t iio_dma_buffer_data_available(struct iio_buffer *buffer); int iio_dma_buffer_set_bytes_per_datum(struct iio_buffer *buffer, size_t bpd); int iio_dma_buffer_set_length(struct iio_buffer *buffer, unsigned int length); @@ -142,4 +144,9 @@ int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue, void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue); void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue); +static inline size_t iio_dma_buffer_space_available(struct iio_buffer *buffer) +{ + return iio_dma_buffer_data_available(buffer); +} + #endif -- 2.34.1
WARNING: multiple messages have this Message-ID (diff)
From: Paul Cercueil <paul@crapouillou.net> To: Jonathan Cameron <jic23@kernel.org> Cc: "Michael Hennerich" <Michael.Hennerich@analog.com>, "Lars-Peter Clausen" <lars@metafoo.de>, "Christian König" <christian.koenig@amd.com>, "Sumit Semwal" <sumit.semwal@linaro.org>, "Jonathan Corbet" <corbet@lwn.net>, "Alexandru Ardelean" <ardeleanalex@gmail.com>, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, "Paul Cercueil" <paul@crapouillou.net> Subject: [PATCH v2 02/12] iio: buffer-dma: Enable buffer write support Date: Mon, 7 Feb 2022 12:59:23 +0000 [thread overview] Message-ID: <20220207125933.81634-3-paul@crapouillou.net> (raw) In-Reply-To: <20220207125933.81634-1-paul@crapouillou.net> Adding write support to the buffer-dma code is easy - the write() function basically needs to do the exact same thing as the read() function: dequeue a block, read or write the data, enqueue the block when entirely processed. Therefore, the iio_buffer_dma_read() and the new iio_buffer_dma_write() now both call a function iio_buffer_dma_io(), which will perform this task. The .space_available() callback can return the exact same value as the .data_available() callback for input buffers, since in both cases we count the exact same thing (the number of bytes in each available block). Note that we preemptively reset block->bytes_used to the buffer's size in iio_dma_buffer_request_update(), as in the future the iio_dma_buffer_enqueue() function won't reset it. v2: - Fix block->state not being reset in iio_dma_buffer_request_update() for output buffers. - Only update block->bytes_used once and add a comment about why we update it. - Add a comment about why we're setting a different state for output buffers in iio_dma_buffer_request_update() - Remove useless cast to bool (!!) in iio_dma_buffer_io() Signed-off-by: Paul Cercueil <paul@crapouillou.net> Reviewed-by: Alexandru Ardelean <ardeleanalex@gmail.com> --- drivers/iio/buffer/industrialio-buffer-dma.c | 88 ++++++++++++++++---- include/linux/iio/buffer-dma.h | 7 ++ 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 1fc91467d1aa..a9f1b673374f 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -195,6 +195,18 @@ static void _iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) block->state = IIO_BLOCK_STATE_DONE; } +static void iio_dma_buffer_queue_wake(struct iio_dma_buffer_queue *queue) +{ + __poll_t flags; + + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) + flags = EPOLLIN | EPOLLRDNORM; + else + flags = EPOLLOUT | EPOLLWRNORM; + + wake_up_interruptible_poll(&queue->buffer.pollq, flags); +} + /** * iio_dma_buffer_block_done() - Indicate that a block has been completed * @block: The completed block @@ -212,7 +224,7 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) spin_unlock_irqrestore(&queue->list_lock, flags); iio_buffer_block_put_atomic(block); - wake_up_interruptible_poll(&queue->buffer.pollq, EPOLLIN | EPOLLRDNORM); + iio_dma_buffer_queue_wake(queue); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done); @@ -241,7 +253,7 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue, } spin_unlock_irqrestore(&queue->list_lock, flags); - wake_up_interruptible_poll(&queue->buffer.pollq, EPOLLIN | EPOLLRDNORM); + iio_dma_buffer_queue_wake(queue); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort); @@ -335,8 +347,24 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) queue->fileio.blocks[i] = block; } - block->state = IIO_BLOCK_STATE_QUEUED; - list_add_tail(&block->head, &queue->incoming); + /* + * block->bytes_used may have been modified previously, e.g. by + * iio_dma_buffer_block_list_abort(). Reset it here to the + * block's so that iio_dma_buffer_io() will work. + */ + block->bytes_used = block->size; + + /* + * If it's an input buffer, mark the block as queued, and + * iio_dma_buffer_enable() will submit it. Otherwise mark it as + * done, which means it's ready to be dequeued. + */ + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) { + block->state = IIO_BLOCK_STATE_QUEUED; + list_add_tail(&block->head, &queue->incoming); + } else { + block->state = IIO_BLOCK_STATE_DONE; + } } out_unlock: @@ -465,20 +493,12 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( return block; } -/** - * iio_dma_buffer_read() - DMA buffer read callback - * @buffer: Buffer to read form - * @n: Number of bytes to read - * @user_buffer: Userspace buffer to copy the data to - * - * Should be used as the read callback for iio_buffer_access_ops - * struct for DMA buffers. - */ -int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, - char __user *user_buffer) +static int iio_dma_buffer_io(struct iio_buffer *buffer, + size_t n, char __user *user_buffer, bool is_write) { struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); struct iio_dma_buffer_block *block; + void *addr; int ret; if (n < buffer->bytes_per_datum) @@ -501,8 +521,13 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, n = rounddown(n, buffer->bytes_per_datum); if (n > block->bytes_used - queue->fileio.pos) n = block->bytes_used - queue->fileio.pos; + addr = block->vaddr + queue->fileio.pos; - if (copy_to_user(user_buffer, block->vaddr + queue->fileio.pos, n)) { + if (is_write) + ret = copy_from_user(addr, user_buffer, n); + else + ret = copy_to_user(user_buffer, addr, n); + if (ret) { ret = -EFAULT; goto out_unlock; } @@ -521,8 +546,39 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, return ret; } + +/** + * iio_dma_buffer_read() - DMA buffer read callback + * @buffer: Buffer to read form + * @n: Number of bytes to read + * @user_buffer: Userspace buffer to copy the data to + * + * Should be used as the read callback for iio_buffer_access_ops + * struct for DMA buffers. + */ +int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, + char __user *user_buffer) +{ + return iio_dma_buffer_io(buffer, n, user_buffer, false); +} EXPORT_SYMBOL_GPL(iio_dma_buffer_read); +/** + * iio_dma_buffer_write() - DMA buffer write callback + * @buffer: Buffer to read form + * @n: Number of bytes to read + * @user_buffer: Userspace buffer to copy the data from + * + * Should be used as the write callback for iio_buffer_access_ops + * struct for DMA buffers. + */ +int iio_dma_buffer_write(struct iio_buffer *buffer, size_t n, + const char __user *user_buffer) +{ + return iio_dma_buffer_io(buffer, n, (__force char *)user_buffer, true); +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_write); + /** * iio_dma_buffer_data_available() - DMA buffer data_available callback * @buf: Buffer to check for data availability diff --git a/include/linux/iio/buffer-dma.h b/include/linux/iio/buffer-dma.h index 18d3702fa95d..490b93f76fa8 100644 --- a/include/linux/iio/buffer-dma.h +++ b/include/linux/iio/buffer-dma.h @@ -132,6 +132,8 @@ int iio_dma_buffer_disable(struct iio_buffer *buffer, struct iio_dev *indio_dev); int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, char __user *user_buffer); +int iio_dma_buffer_write(struct iio_buffer *buffer, size_t n, + const char __user *user_buffer); size_t iio_dma_buffer_data_available(struct iio_buffer *buffer); int iio_dma_buffer_set_bytes_per_datum(struct iio_buffer *buffer, size_t bpd); int iio_dma_buffer_set_length(struct iio_buffer *buffer, unsigned int length); @@ -142,4 +144,9 @@ int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue, void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue); void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue); +static inline size_t iio_dma_buffer_space_available(struct iio_buffer *buffer) +{ + return iio_dma_buffer_data_available(buffer); +} + #endif -- 2.34.1
next prev parent reply other threads:[~2022-02-07 12:59 UTC|newest] Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-02-07 12:59 [PATCH v2 00/12] iio: buffer-dma: write() and new DMABUF based API Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 12:59 ` [PATCH v2 01/12] iio: buffer-dma: Get rid of outgoing queue Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-13 18:57 ` Jonathan Cameron 2022-02-13 18:57 ` Jonathan Cameron 2022-02-13 19:25 ` Paul Cercueil 2022-02-13 19:25 ` Paul Cercueil 2022-03-28 17:17 ` Jonathan Cameron 2022-03-28 17:17 ` Jonathan Cameron 2022-02-07 12:59 ` Paul Cercueil [this message] 2022-02-07 12:59 ` [PATCH v2 02/12] iio: buffer-dma: Enable buffer write support Paul Cercueil 2022-03-28 17:24 ` Jonathan Cameron 2022-03-28 17:24 ` Jonathan Cameron 2022-03-28 18:39 ` Paul Cercueil 2022-03-28 18:39 ` Paul Cercueil 2022-03-29 7:11 ` Nuno Sá 2022-03-29 7:11 ` Nuno Sá 2022-03-28 20:38 ` Andy Shevchenko 2022-03-28 20:38 ` Andy Shevchenko 2022-02-07 12:59 ` [PATCH v2 03/12] iio: buffer-dmaengine: Support specifying buffer direction Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 12:59 ` [PATCH v2 04/12] iio: buffer-dmaengine: Enable write support Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-03-28 17:28 ` Jonathan Cameron 2022-03-28 17:28 ` Jonathan Cameron 2022-02-07 12:59 ` [PATCH v2 05/12] iio: core: Add new DMABUF interface infrastructure Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-03-28 17:37 ` Jonathan Cameron 2022-03-28 17:37 ` Jonathan Cameron 2022-03-28 18:44 ` Paul Cercueil 2022-03-28 18:44 ` Paul Cercueil 2022-03-29 13:36 ` Jonathan Cameron 2022-03-29 13:36 ` Jonathan Cameron 2022-03-28 20:46 ` Andy Shevchenko 2022-03-28 20:46 ` Andy Shevchenko 2022-02-07 12:59 ` [PATCH v2 06/12] iio: buffer-dma: split iio_dma_buffer_fileio_free() function Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 12:59 ` [PATCH v2 07/12] iio: buffer-dma: Use DMABUFs instead of custom solution Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-03-28 17:54 ` Jonathan Cameron 2022-03-28 17:54 ` Jonathan Cameron 2022-03-28 17:54 ` Christian König 2022-03-28 17:54 ` Christian König 2022-03-28 19:16 ` Paul Cercueil 2022-03-28 19:16 ` Paul Cercueil 2022-03-28 20:58 ` Andy Shevchenko 2022-03-28 20:58 ` Andy Shevchenko 2022-02-07 12:59 ` [PATCH v2 08/12] iio: buffer-dma: Implement new DMABUF based userspace API Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 12:59 ` [PATCH v2 09/12] iio: buffer-dmaengine: Support " Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 12:59 ` [PATCH v2 10/12] iio: core: Add support for cyclic buffers Paul Cercueil 2022-02-07 12:59 ` Paul Cercueil 2022-02-07 13:01 ` [PATCH v2 11/12] iio: buffer-dmaengine: " Paul Cercueil 2022-02-07 13:01 ` Paul Cercueil 2022-02-07 13:01 ` [PATCH v2 12/12] Documentation: iio: Document high-speed DMABUF based API Paul Cercueil 2022-02-07 13:01 ` Paul Cercueil 2022-03-29 8:54 ` Daniel Vetter 2022-03-29 8:54 ` Daniel Vetter 2022-03-29 9:47 ` Paul Cercueil 2022-03-29 9:47 ` Paul Cercueil 2022-03-29 14:07 ` Daniel Vetter 2022-03-29 14:07 ` Daniel Vetter 2022-03-29 17:34 ` Paul Cercueil 2022-03-29 17:34 ` Paul Cercueil 2022-03-30 9:22 ` Daniel Vetter 2022-03-30 9:22 ` Daniel Vetter 2022-02-13 18:46 ` [PATCH v2 00/12] iio: buffer-dma: write() and new " Jonathan Cameron 2022-02-13 18:46 ` Jonathan Cameron 2022-02-15 17:43 ` Paul Cercueil 2022-02-15 17:43 ` Paul Cercueil 2022-03-29 8:33 ` Daniel Vetter 2022-03-29 8:33 ` Daniel Vetter 2022-03-29 9:11 ` Paul Cercueil 2022-03-29 9:11 ` Paul Cercueil 2022-03-29 14:10 ` Daniel Vetter 2022-03-29 14:10 ` Daniel Vetter 2022-03-29 17:16 ` Paul Cercueil 2022-03-29 17:16 ` Paul Cercueil 2022-03-30 9:19 ` Daniel Vetter 2022-03-30 9:19 ` Daniel Vetter
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=20220207125933.81634-3-paul@crapouillou.net \ --to=paul@crapouillou.net \ --cc=Michael.Hennerich@analog.com \ --cc=ardeleanalex@gmail.com \ --cc=christian.koenig@amd.com \ --cc=corbet@lwn.net \ --cc=dri-devel@lists.freedesktop.org \ --cc=jic23@kernel.org \ --cc=linaro-mm-sig@lists.linaro.org \ --cc=linux-doc@vger.kernel.org \ --cc=linux-iio@vger.kernel.org \ --cc=linux-kernel@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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.