@@ -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);
@@ -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;
}