diff mbox series

[2/5] iov_iter: introduce type for preregistered dma tags

Message ID 20220726173814.2264573-3-kbusch@fb.com (mailing list archive)
State New
Headers show
Series dma mapping optimisations | expand

Commit Message

Keith Busch July 26, 2022, 5:38 p.m. UTC
From: Keith Busch <kbusch@kernel.org>

Introduce a new iov_iter type representing a pre-registered DMA address
tag. The tag is an opaque cookie specific to the lower level driver that
created it, and can be referenced at any arbitrary offset.

Signed-off-by: Keith Busch <kbusch@kernel.org>
---
 include/linux/uio.h |  9 +++++++++
 lib/iov_iter.c      | 25 ++++++++++++++++++++++---
 2 files changed, 31 insertions(+), 3 deletions(-)

Comments

Al Viro July 26, 2022, 11:10 p.m. UTC | #1
On Tue, Jul 26, 2022 at 10:38:11AM -0700, Keith Busch wrote:

> +void iov_iter_dma_tag(struct iov_iter *i, unsigned int direction,
> +			void *dma_tag, unsigned int dma_offset,
> +			unsigned long nr_segs, size_t count)
> +{
> +	WARN_ON(direction & ~(READ | WRITE));
> +	*i = (struct iov_iter){
> +		.iter_type = ITER_DMA_TAG,
> +		.data_source = direction,
> +		.nr_segs = nr_segs,

Could you can that cargo-culting?  Just what the hell is nr_segs
here?
Keith Busch July 27, 2022, 1:52 p.m. UTC | #2
On Wed, Jul 27, 2022 at 12:10:33AM +0100, Al Viro wrote:
> On Tue, Jul 26, 2022 at 10:38:11AM -0700, Keith Busch wrote:
> 
> > +void iov_iter_dma_tag(struct iov_iter *i, unsigned int direction,
> > +			void *dma_tag, unsigned int dma_offset,
> > +			unsigned long nr_segs, size_t count)
> > +{
> > +	WARN_ON(direction & ~(READ | WRITE));
> > +	*i = (struct iov_iter){
> > +		.iter_type = ITER_DMA_TAG,
> > +		.data_source = direction,
> > +		.nr_segs = nr_segs,
> 
> Could you can that cargo-culting?  Just what the hell is nr_segs
> here?

Thanks for the catch. Setting nr_segs here is useless carry-over from an
earlier version when I thought it would be used to build the request. Turns out
it's not used at all.
diff mbox series

Patch

diff --git a/include/linux/uio.h b/include/linux/uio.h
index 34ba4a731179..de8af68eacb3 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -26,6 +26,7 @@  enum iter_type {
 	ITER_PIPE,
 	ITER_XARRAY,
 	ITER_DISCARD,
+	ITER_DMA_TAG,
 };
 
 struct iov_iter_state {
@@ -46,6 +47,7 @@  struct iov_iter {
 		const struct bio_vec *bvec;
 		struct xarray *xarray;
 		struct pipe_inode_info *pipe;
+		void *dma_tag;
 	};
 	union {
 		unsigned long nr_segs;
@@ -85,6 +87,11 @@  static inline bool iov_iter_is_bvec(const struct iov_iter *i)
 	return iov_iter_type(i) == ITER_BVEC;
 }
 
+static inline bool iov_iter_is_dma_tag(const struct iov_iter *i)
+{
+	return iov_iter_type(i) == ITER_DMA_TAG;
+}
+
 static inline bool iov_iter_is_pipe(const struct iov_iter *i)
 {
 	return iov_iter_type(i) == ITER_PIPE;
@@ -229,6 +236,8 @@  void iov_iter_kvec(struct iov_iter *i, unsigned int direction, const struct kvec
 			unsigned long nr_segs, size_t count);
 void iov_iter_bvec(struct iov_iter *i, unsigned int direction, const struct bio_vec *bvec,
 			unsigned long nr_segs, size_t count);
+void iov_iter_dma_tag(struct iov_iter *i, unsigned int direction, void *dma_tag,
+			unsigned int dma_offset, unsigned long nr_segs, size_t count);
 void iov_iter_pipe(struct iov_iter *i, unsigned int direction, struct pipe_inode_info *pipe,
 			size_t count);
 void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count);
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 507e732ef7cf..e26cb0889820 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1077,6 +1077,9 @@  void iov_iter_advance(struct iov_iter *i, size_t size)
 		i->count -= size;
 	} else if (iov_iter_is_discard(i)) {
 		i->count -= size;
+	} else if (iov_iter_is_dma_tag(i)) {
+		i->iov_offset += size;
+		i->count -= size;
 	}
 }
 EXPORT_SYMBOL(iov_iter_advance);
@@ -1201,6 +1204,22 @@  void iov_iter_bvec(struct iov_iter *i, unsigned int direction,
 }
 EXPORT_SYMBOL(iov_iter_bvec);
 
+void iov_iter_dma_tag(struct iov_iter *i, unsigned int direction,
+			void *dma_tag, unsigned int dma_offset,
+			unsigned long nr_segs, size_t count)
+{
+	WARN_ON(direction & ~(READ | WRITE));
+	*i = (struct iov_iter){
+		.iter_type = ITER_DMA_TAG,
+		.data_source = direction,
+		.nr_segs = nr_segs,
+		.dma_tag = dma_tag,
+		.iov_offset = dma_offset,
+		.count = count
+	};
+}
+EXPORT_SYMBOL(iov_iter_dma_tag);
+
 void iov_iter_pipe(struct iov_iter *i, unsigned int direction,
 			struct pipe_inode_info *pipe,
 			size_t count)
@@ -2124,8 +2143,8 @@  EXPORT_SYMBOL(import_single_range);
  */
 void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
 {
-	if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i)) &&
-			 !iov_iter_is_kvec(i))
+	if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i) &&
+			 !iov_iter_is_dma_tag(i)) && !iov_iter_is_kvec(i))
 		return;
 	i->iov_offset = state->iov_offset;
 	i->count = state->count;
@@ -2141,7 +2160,7 @@  void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
 	BUILD_BUG_ON(sizeof(struct iovec) != sizeof(struct kvec));
 	if (iov_iter_is_bvec(i))
 		i->bvec -= state->nr_segs - i->nr_segs;
-	else
+	else if (!iov_iter_is_dma_tag(i))
 		i->iov -= state->nr_segs - i->nr_segs;
 	i->nr_segs = state->nr_segs;
 }