* [PATCH v3 01/16] iosys-map: Add offset to iosys_map_memcpy_to()
[not found] <20220216174147.3073235-1-lucas.demarchi@intel.com>
@ 2022-02-16 17:41 ` Lucas De Marchi
2022-02-16 17:41 ` [PATCH v3 02/16] iosys-map: Add a few more helpers Lucas De Marchi
1 sibling, 0 replies; 4+ messages in thread
From: Lucas De Marchi @ 2022-02-16 17:41 UTC (permalink / raw)
To: intel-gfx, dri-devel
Cc: John Harrison, Matthew Brost, Daniele Ceraolo Spurio, Matt Roper,
Thomas Hellström, Thomas Zimmermann, Christian König,
Sumit Semwal, Lucas De Marchi, linux-kernel
In certain situations it's useful to be able to write to an
offset of the mapping. Add a dst_offset to iosys_map_memcpy_to().
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Christian König <christian.koenig@amd.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_cache.c | 2 +-
drivers/gpu/drm/drm_fb_helper.c | 2 +-
include/linux/iosys-map.h | 17 +++++++++--------
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 66597e411764..c3e6e615bf09 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -218,7 +218,7 @@ static void memcpy_fallback(struct iosys_map *dst,
if (!dst->is_iomem && !src->is_iomem) {
memcpy(dst->vaddr, src->vaddr, len);
} else if (!src->is_iomem) {
- iosys_map_memcpy_to(dst, src->vaddr, len);
+ iosys_map_memcpy_to(dst, 0, src->vaddr, len);
} else if (!dst->is_iomem) {
memcpy_fromio(dst->vaddr, src->vaddr_iomem, len);
} else {
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 409d8dd7f868..d265a73313c9 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -385,7 +385,7 @@ static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper,
iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
for (y = clip->y1; y < clip->y2; y++) {
- iosys_map_memcpy_to(dst, src, len);
+ iosys_map_memcpy_to(dst, 0, src, len);
iosys_map_incr(dst, fb->pitches[0]);
src += fb->pitches[0];
}
diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index f4186f91caa6..edd730b1e899 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -220,22 +220,23 @@ static inline void iosys_map_clear(struct iosys_map *map)
}
/**
- * iosys_map_memcpy_to - Memcpy into iosys mapping
+ * iosys_map_memcpy_to - Memcpy into offset of iosys_map
* @dst: The iosys_map structure
+ * @dst_offset: The offset from which to copy
* @src: The source buffer
* @len: The number of byte in src
*
- * Copies data into a iosys mapping. The source buffer is in system
- * memory. Depending on the buffer's location, the helper picks the correct
- * method of accessing the memory.
+ * Copies data into a iosys_map with an offset. The source buffer is in
+ * system memory. Depending on the buffer's location, the helper picks the
+ * correct method of accessing the memory.
*/
-static inline void iosys_map_memcpy_to(struct iosys_map *dst, const void *src,
- size_t len)
+static inline void iosys_map_memcpy_to(struct iosys_map *dst, size_t dst_offset,
+ const void *src, size_t len)
{
if (dst->is_iomem)
- memcpy_toio(dst->vaddr_iomem, src, len);
+ memcpy_toio(dst->vaddr_iomem + dst_offset, src, len);
else
- memcpy(dst->vaddr, src, len);
+ memcpy(dst->vaddr + dst_offset, src, len);
}
/**
--
2.35.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 02/16] iosys-map: Add a few more helpers
[not found] <20220216174147.3073235-1-lucas.demarchi@intel.com>
2022-02-16 17:41 ` [PATCH v3 01/16] iosys-map: Add offset to iosys_map_memcpy_to() Lucas De Marchi
@ 2022-02-16 17:41 ` Lucas De Marchi
2022-02-17 8:42 ` Thomas Zimmermann
1 sibling, 1 reply; 4+ messages in thread
From: Lucas De Marchi @ 2022-02-16 17:41 UTC (permalink / raw)
To: intel-gfx, dri-devel
Cc: John Harrison, Matthew Brost, Daniele Ceraolo Spurio, Matt Roper,
Thomas Hellström, Thomas Zimmermann, Christian König,
Sumit Semwal, Lucas De Marchi, Mauro Carvalho Chehab,
linux-kernel, Matt Atwood
First the simplest ones:
- iosys_map_memset(): when abstracting system and I/O memory,
just like the memcpy() use case, memset() also has dedicated
functions to be called for using IO memory.
- iosys_map_memcpy_from(): we may need to copy data from I/O
memory, not only to.
In certain situations it's useful to be able to read or write to an
offset that is calculated by having the memory layout given by a struct
declaration. Usually we are going to read/write a u8, u16, u32 or u64.
As a pre-requisite for the implementation, add iosys_map_memcpy_from()
to be the equivalent of iosys_map_memcpy_to(), but in the other
direction. Then add 2 pairs of macros:
- iosys_map_rd() / iosys_map_wr()
- iosys_map_rd_field() / iosys_map_wr_field()
The first pair takes the C-type and offset to read/write. The second
pair uses a struct describing the layout of the mapping in order to
calculate the offset and size being read/written.
We could use readb, readw, readl, readq and the write* counterparts,
however due to alignment issues this may not work on all architectures.
If alignment needs to be checked to call the right function, it's not
possible to decide at compile-time which function to call: so just leave
the decision to the memcpy function that will do exactly that.
Finally, in order to use the above macros with a map derived from
another, add another initializer: IOSYS_MAP_INIT_OFFSET().
v2:
- Rework IOSYS_MAP_INIT_OFFSET() so it doesn't rely on aliasing rules
within the union
- Add offset to both iosys_map_rd_field() and iosys_map_wr_field() to
allow the struct itself to be at an offset from the mapping
- Add documentation to iosys_map_rd_field() with example and expected
memory layout
v3:
- Drop kernel.h include as it's not needed anymore
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Christian König <christian.koenig@amd.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
---
include/linux/iosys-map.h | 201 ++++++++++++++++++++++++++++++++++++++
1 file changed, 201 insertions(+)
diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index edd730b1e899..e69a002d5aa4 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -120,6 +120,45 @@ struct iosys_map {
.is_iomem = false, \
}
+/**
+ * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map
+ * @map_: The dma-buf mapping structure to copy from
+ * @offset_: Offset to add to the other mapping
+ *
+ * Initializes a new iosys_map struct based on another passed as argument. It
+ * does a shallow copy of the struct so it's possible to update the back storage
+ * without changing where the original map points to. It is the equivalent of
+ * doing:
+ *
+ * .. code-block:: c
+ *
+ * iosys_map map = other_map;
+ * iosys_map_incr(&map, &offset);
+ *
+ * Example usage:
+ *
+ * .. code-block:: c
+ *
+ * void foo(struct device *dev, struct iosys_map *base_map)
+ * {
+ * ...
+ * struct iosys_map map = IOSYS_MAP_INIT_OFFSET(base_map, FIELD_OFFSET);
+ * ...
+ * }
+ *
+ * The advantage of using the initializer over just increasing the offset with
+ * iosys_map_incr() like above is that the new map will always point to the
+ * right place of the buffer during its scope. It reduces the risk of updating
+ * the wrong part of the buffer and having no compiler warning about that. If
+ * the assignment to IOSYS_MAP_INIT_OFFSET() is forgotten, the compiler can warn
+ * about the use of uninitialized variable.
+ */
+#define IOSYS_MAP_INIT_OFFSET(map_, offset_) ({ \
+ struct iosys_map copy = *map_; \
+ iosys_map_incr(©, offset_); \
+ copy; \
+})
+
/**
* iosys_map_set_vaddr - Sets a iosys mapping structure to an address in system memory
* @map: The iosys_map structure
@@ -239,6 +278,26 @@ static inline void iosys_map_memcpy_to(struct iosys_map *dst, size_t dst_offset,
memcpy(dst->vaddr + dst_offset, src, len);
}
+/**
+ * iosys_map_memcpy_from - Memcpy from iosys_map into system memory
+ * @dst: Destination in system memory
+ * @src: The iosys_map structure
+ * @src_offset: The offset from which to copy
+ * @len: The number of byte in src
+ *
+ * Copies data from a iosys_map with an offset. The dest buffer is in
+ * system memory. Depending on the mapping location, the helper picks the
+ * correct method of accessing the memory.
+ */
+static inline void iosys_map_memcpy_from(void *dst, const struct iosys_map *src,
+ size_t src_offset, size_t len)
+{
+ if (src->is_iomem)
+ memcpy_fromio(dst, src->vaddr_iomem + src_offset, len);
+ else
+ memcpy(dst, src->vaddr + src_offset, len);
+}
+
/**
* iosys_map_incr - Increments the address stored in a iosys mapping
* @map: The iosys_map structure
@@ -255,4 +314,146 @@ static inline void iosys_map_incr(struct iosys_map *map, size_t incr)
map->vaddr += incr;
}
+/**
+ * iosys_map_memset - Memset iosys_map
+ * @dst: The iosys_map structure
+ * @offset: Offset from dst where to start setting value
+ * @value: The value to set
+ * @len: The number of bytes to set in dst
+ *
+ * Set value in iosys_map. Depending on the buffer's location, the helper
+ * picks the correct method of accessing the memory.
+ */
+static inline void iosys_map_memset(struct iosys_map *dst, size_t offset,
+ int value, size_t len)
+{
+ if (dst->is_iomem)
+ memset_io(dst->vaddr_iomem + offset, value, len);
+ else
+ memset(dst->vaddr + offset, value, len);
+}
+
+/**
+ * iosys_map_rd - Read a C-type value from the iosys_map
+ *
+ * @map__: The iosys_map structure
+ * @offset__: The offset from which to read
+ * @type__: Type of the value being read
+ *
+ * Read a C type value from iosys_map, handling possible un-aligned accesses to
+ * the mapping.
+ *
+ * Returns:
+ * The value read from the mapping.
+ */
+#define iosys_map_rd(map__, offset__, type__) ({ \
+ type__ val; \
+ iosys_map_memcpy_from(&val, map__, offset__, sizeof(val)); \
+ val; \
+})
+
+/**
+ * iosys_map_wr - Write a C-type value to the iosys_map
+ *
+ * @map__: The iosys_map structure
+ * @offset__: The offset from the mapping to write to
+ * @type__: Type of the value being written
+ * @val__: Value to write
+ *
+ * Write a C-type value to the iosys_map, handling possible un-aligned accesses
+ * to the mapping.
+ */
+#define iosys_map_wr(map__, offset__, type__, val__) ({ \
+ type__ val = (val__); \
+ iosys_map_memcpy_to(map__, offset__, &val, sizeof(val)); \
+})
+
+/**
+ * iosys_map_rd_field - Read a member from a struct in the iosys_map
+ *
+ * @map__: The iosys_map structure
+ * @struct_offset__: Offset from the beggining of the map, where the struct
+ * is located
+ * @struct_type__: The struct describing the layout of the mapping
+ * @field__: Member of the struct to read
+ *
+ * Read a value from iosys_map considering its layout is described by a C struct
+ * starting at @struct_offset__. The field offset and size is calculated and its
+ * value read handling possible un-aligned memory accesses. For example: suppose
+ * there is a @struct foo defined as below and the value ``foo.field2.inner2``
+ * needs to be read from the iosys_map:
+ *
+ * .. code-block:: c
+ *
+ * struct foo {
+ * int field1;
+ * struct {
+ * int inner1;
+ * int inner2;
+ * } field2;
+ * int field3;
+ * } __packed;
+ *
+ * This is the expected memory layout of a buffer using iosys_map_rd_field():
+ *
+ * +------------------------------+--------------------------+
+ * | Address | Content |
+ * +==============================+==========================+
+ * | buffer + 0000 | start of mmapped buffer |
+ * | | pointed by iosys_map |
+ * +------------------------------+--------------------------+
+ * | ... | ... |
+ * +------------------------------+--------------------------+
+ * | buffer + ``struct_offset__`` | start of ``struct foo`` |
+ * +------------------------------+--------------------------+
+ * | ... | ... |
+ * +------------------------------+--------------------------+
+ * | buffer + wwww | ``foo.field2.inner2`` |
+ * +------------------------------+--------------------------+
+ * | ... | ... |
+ * +------------------------------+--------------------------+
+ * | buffer + yyyy | end of ``struct foo`` |
+ * +------------------------------+--------------------------+
+ * | ... | ... |
+ * +------------------------------+--------------------------+
+ * | buffer + zzzz | end of mmaped buffer |
+ * +------------------------------+--------------------------+
+ *
+ * Values automatically calculated by this macro or not needed are denoted by
+ * wwww, yyyy and zzzz. This is the code to read that value:
+ *
+ * .. code-block:: c
+ *
+ * x = iosys_map_rd_field(&map, offset, struct foo, field2.inner2);
+ *
+ * Returns:
+ * The value read from the mapping.
+ */
+#define iosys_map_rd_field(map__, struct_offset__, struct_type__, field__) ({ \
+ struct_type__ *s; \
+ iosys_map_rd(map__, struct_offset__ + offsetof(struct_type__, field__), \
+ typeof(s->field__)); \
+})
+
+/**
+ * iosys_map_wr_field - Write to a member of a struct in the iosys_map
+ *
+ * @map__: The iosys_map structure
+ * @struct_offset__: Offset from the beggining of the map, where the struct
+ * is located
+ * @struct_type__: The struct describing the layout of the mapping
+ * @field__: Member of the struct to read
+ * @val__: Value to write
+ *
+ * Write a value to the iosys_map considering its layout is described by a C struct
+ * starting at @struct_offset__. The field offset and size is calculated and the
+ * @val__ is written handling possible un-aligned memory accesses. Refer to
+ * iosys_map_rd_field() for expected usage and memory layout.
+ */
+#define iosys_map_wr_field(map__, struct_offset__, struct_type__, field__, val__) ({ \
+ struct_type__ *s; \
+ iosys_map_wr(map__, struct_offset__ + offsetof(struct_type__, field__), \
+ typeof(s->field__), val__); \
+})
+
#endif /* __IOSYS_MAP_H__ */
--
2.35.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 02/16] iosys-map: Add a few more helpers
2022-02-16 17:41 ` [PATCH v3 02/16] iosys-map: Add a few more helpers Lucas De Marchi
@ 2022-02-17 8:42 ` Thomas Zimmermann
2022-02-20 4:28 ` Lucas De Marchi
0 siblings, 1 reply; 4+ messages in thread
From: Thomas Zimmermann @ 2022-02-17 8:42 UTC (permalink / raw)
To: Lucas De Marchi, intel-gfx, dri-devel
Cc: Matthew Brost, Thomas Hellström, Matt Atwood, linux-kernel,
Sumit Semwal, Daniele Ceraolo Spurio, Mauro Carvalho Chehab,
Christian König, John Harrison
[-- Attachment #1.1: Type: text/plain, Size: 11716 bytes --]
Hi
Am 16.02.22 um 18:41 schrieb Lucas De Marchi:
> First the simplest ones:
>
> - iosys_map_memset(): when abstracting system and I/O memory,
> just like the memcpy() use case, memset() also has dedicated
> functions to be called for using IO memory.
> - iosys_map_memcpy_from(): we may need to copy data from I/O
> memory, not only to.
>
> In certain situations it's useful to be able to read or write to an
> offset that is calculated by having the memory layout given by a struct
> declaration. Usually we are going to read/write a u8, u16, u32 or u64.
>
> As a pre-requisite for the implementation, add iosys_map_memcpy_from()
> to be the equivalent of iosys_map_memcpy_to(), but in the other
> direction. Then add 2 pairs of macros:
>
> - iosys_map_rd() / iosys_map_wr()
> - iosys_map_rd_field() / iosys_map_wr_field()
>
> The first pair takes the C-type and offset to read/write. The second
> pair uses a struct describing the layout of the mapping in order to
> calculate the offset and size being read/written.
>
> We could use readb, readw, readl, readq and the write* counterparts,
> however due to alignment issues this may not work on all architectures.
> If alignment needs to be checked to call the right function, it's not
> possible to decide at compile-time which function to call: so just leave
> the decision to the memcpy function that will do exactly that.
>
> Finally, in order to use the above macros with a map derived from
> another, add another initializer: IOSYS_MAP_INIT_OFFSET().
>
> v2:
> - Rework IOSYS_MAP_INIT_OFFSET() so it doesn't rely on aliasing rules
> within the union
> - Add offset to both iosys_map_rd_field() and iosys_map_wr_field() to
> allow the struct itself to be at an offset from the mapping
> - Add documentation to iosys_map_rd_field() with example and expected
> memory layout
> v3:
> - Drop kernel.h include as it's not needed anymore
>
> Cc: Sumit Semwal <sumit.semwal@linaro.org>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
> Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
> include/linux/iosys-map.h | 201 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 201 insertions(+)
>
> diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
> index edd730b1e899..e69a002d5aa4 100644
> --- a/include/linux/iosys-map.h
> +++ b/include/linux/iosys-map.h
> @@ -120,6 +120,45 @@ struct iosys_map {
> .is_iomem = false, \
> }
>
> +/**
> + * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map
> + * @map_: The dma-buf mapping structure to copy from
> + * @offset_: Offset to add to the other mapping
> + *
> + * Initializes a new iosys_map struct based on another passed as argument. It
> + * does a shallow copy of the struct so it's possible to update the back storage
> + * without changing where the original map points to. It is the equivalent of
> + * doing:
> + *
> + * .. code-block:: c
> + *
> + * iosys_map map = other_map;
> + * iosys_map_incr(&map, &offset);
> + *
> + * Example usage:
> + *
> + * .. code-block:: c
> + *
> + * void foo(struct device *dev, struct iosys_map *base_map)
> + * {
> + * ...
> + * struct iosys_map map = IOSYS_MAP_INIT_OFFSET(base_map, FIELD_OFFSET);
> + * ...
> + * }
> + *
> + * The advantage of using the initializer over just increasing the offset with
> + * iosys_map_incr() like above is that the new map will always point to the
> + * right place of the buffer during its scope. It reduces the risk of updating
> + * the wrong part of the buffer and having no compiler warning about that. If
> + * the assignment to IOSYS_MAP_INIT_OFFSET() is forgotten, the compiler can warn
> + * about the use of uninitialized variable.
> + */
> +#define IOSYS_MAP_INIT_OFFSET(map_, offset_) ({ \
> + struct iosys_map copy = *map_; \
> + iosys_map_incr(©, offset_); \
> + copy; \
> +})
> +
> /**
> * iosys_map_set_vaddr - Sets a iosys mapping structure to an address in system memory
> * @map: The iosys_map structure
> @@ -239,6 +278,26 @@ static inline void iosys_map_memcpy_to(struct iosys_map *dst, size_t dst_offset,
> memcpy(dst->vaddr + dst_offset, src, len);
> }
>
> +/**
> + * iosys_map_memcpy_from - Memcpy from iosys_map into system memory
> + * @dst: Destination in system memory
> + * @src: The iosys_map structure
> + * @src_offset: The offset from which to copy
> + * @len: The number of byte in src
> + *
> + * Copies data from a iosys_map with an offset. The dest buffer is in
> + * system memory. Depending on the mapping location, the helper picks the
> + * correct method of accessing the memory.
> + */
> +static inline void iosys_map_memcpy_from(void *dst, const struct iosys_map *src,
> + size_t src_offset, size_t len)
> +{
> + if (src->is_iomem)
> + memcpy_fromio(dst, src->vaddr_iomem + src_offset, len);
> + else
> + memcpy(dst, src->vaddr + src_offset, len);
> +}
> +
> /**
> * iosys_map_incr - Increments the address stored in a iosys mapping
> * @map: The iosys_map structure
> @@ -255,4 +314,146 @@ static inline void iosys_map_incr(struct iosys_map *map, size_t incr)
> map->vaddr += incr;
> }
>
> +/**
> + * iosys_map_memset - Memset iosys_map
> + * @dst: The iosys_map structure
> + * @offset: Offset from dst where to start setting value
> + * @value: The value to set
> + * @len: The number of bytes to set in dst
> + *
> + * Set value in iosys_map. Depending on the buffer's location, the helper
> + * picks the correct method of accessing the memory.
> + */
> +static inline void iosys_map_memset(struct iosys_map *dst, size_t offset,
> + int value, size_t len)
> +{
> + if (dst->is_iomem)
> + memset_io(dst->vaddr_iomem + offset, value, len);
> + else
> + memset(dst->vaddr + offset, value, len);
> +}
> +
> +/**
> + * iosys_map_rd - Read a C-type value from the iosys_map
> + *
> + * @map__: The iosys_map structure
> + * @offset__: The offset from which to read
> + * @type__: Type of the value being read
> + *
> + * Read a C type value from iosys_map, handling possible un-aligned accesses to
> + * the mapping.
> + *
> + * Returns:
> + * The value read from the mapping.
> + */
> +#define iosys_map_rd(map__, offset__, type__) ({ \
> + type__ val; \
> + iosys_map_memcpy_from(&val, map__, offset__, sizeof(val)); \
> + val; \
> +})
> +
> +/**
> + * iosys_map_wr - Write a C-type value to the iosys_map
> + *
> + * @map__: The iosys_map structure
> + * @offset__: The offset from the mapping to write to
> + * @type__: Type of the value being written
> + * @val__: Value to write
> + *
> + * Write a C-type value to the iosys_map, handling possible un-aligned accesses
> + * to the mapping.
> + */
> +#define iosys_map_wr(map__, offset__, type__, val__) ({ \
> + type__ val = (val__); \
> + iosys_map_memcpy_to(map__, offset__, &val, sizeof(val)); \
> +})
> +
> +/**
> + * iosys_map_rd_field - Read a member from a struct in the iosys_map
> + *
> + * @map__: The iosys_map structure
> + * @struct_offset__: Offset from the beggining of the map, where the struct
> + * is located
> + * @struct_type__: The struct describing the layout of the mapping
> + * @field__: Member of the struct to read
> + *
> + * Read a value from iosys_map considering its layout is described by a C struct
> + * starting at @struct_offset__. The field offset and size is calculated and its
> + * value read handling possible un-aligned memory accesses. For example: suppose
> + * there is a @struct foo defined as below and the value ``foo.field2.inner2``
> + * needs to be read from the iosys_map:
> + *
> + * .. code-block:: c
> + *
> + * struct foo {
> + * int field1;
> + * struct {
> + * int inner1;
> + * int inner2;
> + * } field2;
> + * int field3;
> + * } __packed;
> + *
> + * This is the expected memory layout of a buffer using iosys_map_rd_field():
> + *
> + * +------------------------------+--------------------------+
> + * | Address | Content |
> + * +==============================+==========================+
> + * | buffer + 0000 | start of mmapped buffer |
> + * | | pointed by iosys_map |
> + * +------------------------------+--------------------------+
> + * | ... | ... |
> + * +------------------------------+--------------------------+
> + * | buffer + ``struct_offset__`` | start of ``struct foo`` |
> + * +------------------------------+--------------------------+
> + * | ... | ... |
> + * +------------------------------+--------------------------+
> + * | buffer + wwww | ``foo.field2.inner2`` |
> + * +------------------------------+--------------------------+
> + * | ... | ... |
> + * +------------------------------+--------------------------+
> + * | buffer + yyyy | end of ``struct foo`` |
> + * +------------------------------+--------------------------+
> + * | ... | ... |
> + * +------------------------------+--------------------------+
> + * | buffer + zzzz | end of mmaped buffer |
> + * +------------------------------+--------------------------+
> + *
> + * Values automatically calculated by this macro or not needed are denoted by
> + * wwww, yyyy and zzzz. This is the code to read that value:
> + *
> + * .. code-block:: c
> + *
> + * x = iosys_map_rd_field(&map, offset, struct foo, field2.inner2);
> + *
> + * Returns:
> + * The value read from the mapping.
> + */
> +#define iosys_map_rd_field(map__, struct_offset__, struct_type__, field__) ({ \
> + struct_type__ *s; \
> + iosys_map_rd(map__, struct_offset__ + offsetof(struct_type__, field__), \
> + typeof(s->field__)); \
> +})
> +
> +/**
> + * iosys_map_wr_field - Write to a member of a struct in the iosys_map
> + *
> + * @map__: The iosys_map structure
> + * @struct_offset__: Offset from the beggining of the map, where the struct
> + * is located
> + * @struct_type__: The struct describing the layout of the mapping
> + * @field__: Member of the struct to read
> + * @val__: Value to write
> + *
> + * Write a value to the iosys_map considering its layout is described by a C struct
> + * starting at @struct_offset__. The field offset and size is calculated and the
> + * @val__ is written handling possible un-aligned memory accesses. Refer to
> + * iosys_map_rd_field() for expected usage and memory layout.
> + */
> +#define iosys_map_wr_field(map__, struct_offset__, struct_type__, field__, val__) ({ \
> + struct_type__ *s; \
> + iosys_map_wr(map__, struct_offset__ + offsetof(struct_type__, field__), \
> + typeof(s->field__), val__); \
> +})
> +
> #endif /* __IOSYS_MAP_H__ */
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 02/16] iosys-map: Add a few more helpers
2022-02-17 8:42 ` Thomas Zimmermann
@ 2022-02-20 4:28 ` Lucas De Marchi
0 siblings, 0 replies; 4+ messages in thread
From: Lucas De Marchi @ 2022-02-20 4:28 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: intel-gfx, dri-devel, Matthew Brost, Thomas Hellström,
Matt Atwood, linux-kernel, Sumit Semwal, Daniele Ceraolo Spurio,
Mauro Carvalho Chehab, Christian König, John Harrison
On Thu, Feb 17, 2022 at 09:42:08AM +0100, Thomas Zimmermann wrote:
>Hi
>
>Am 16.02.22 um 18:41 schrieb Lucas De Marchi:
>>First the simplest ones:
>>
>> - iosys_map_memset(): when abstracting system and I/O memory,
>> just like the memcpy() use case, memset() also has dedicated
>> functions to be called for using IO memory.
>> - iosys_map_memcpy_from(): we may need to copy data from I/O
>> memory, not only to.
>>
>>In certain situations it's useful to be able to read or write to an
>>offset that is calculated by having the memory layout given by a struct
>>declaration. Usually we are going to read/write a u8, u16, u32 or u64.
>>
>>As a pre-requisite for the implementation, add iosys_map_memcpy_from()
>>to be the equivalent of iosys_map_memcpy_to(), but in the other
>>direction. Then add 2 pairs of macros:
>>
>> - iosys_map_rd() / iosys_map_wr()
>> - iosys_map_rd_field() / iosys_map_wr_field()
>>
>>The first pair takes the C-type and offset to read/write. The second
>>pair uses a struct describing the layout of the mapping in order to
>>calculate the offset and size being read/written.
>>
>>We could use readb, readw, readl, readq and the write* counterparts,
>>however due to alignment issues this may not work on all architectures.
>>If alignment needs to be checked to call the right function, it's not
>>possible to decide at compile-time which function to call: so just leave
>>the decision to the memcpy function that will do exactly that.
>>
>>Finally, in order to use the above macros with a map derived from
>>another, add another initializer: IOSYS_MAP_INIT_OFFSET().
>>
>>v2:
>> - Rework IOSYS_MAP_INIT_OFFSET() so it doesn't rely on aliasing rules
>> within the union
>> - Add offset to both iosys_map_rd_field() and iosys_map_wr_field() to
>> allow the struct itself to be at an offset from the mapping
>> - Add documentation to iosys_map_rd_field() with example and expected
>> memory layout
>>v3:
>> - Drop kernel.h include as it's not needed anymore
>>
>>Cc: Sumit Semwal <sumit.semwal@linaro.org>
>>Cc: Christian König <christian.koenig@amd.com>
>>Cc: Thomas Zimmermann <tzimmermann@suse.de>
>>Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
>>Cc: dri-devel@lists.freedesktop.org
>>Cc: linux-kernel@vger.kernel.org
>>Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
>>Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
>>Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
>
>Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Thanks. I applied the first 2 patches to drm-intel-next.
The rest can't be applied as there are conflicts between drm-intel-next
and drm-intel-gt-next. I should have merged the rename to
drm-intel-gt-next since the guc patches need to be applied there.
I guess the rest will have to wait some tree propagation.
Lucas De Marchi
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-02-20 4:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20220216174147.3073235-1-lucas.demarchi@intel.com>
2022-02-16 17:41 ` [PATCH v3 01/16] iosys-map: Add offset to iosys_map_memcpy_to() Lucas De Marchi
2022-02-16 17:41 ` [PATCH v3 02/16] iosys-map: Add a few more helpers Lucas De Marchi
2022-02-17 8:42 ` Thomas Zimmermann
2022-02-20 4:28 ` Lucas De Marchi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).