mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH master 00/23] treewide: fix bugs using DMA API
@ 2024-04-24  6:40 Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 01/23] habv4: use DMA-capable memory for getting event from BootROM Ahmad Fatoum
                   ` (23 more replies)
  0 siblings, 24 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz

As described in commi b986aad24ab8 ("mci: core: allocate memory used
for DMA with dma_alloc"), the recent fix to ARMv8 cache operations in
commit 65ef5d885263 ("ARM64: let 'end' point after the range in cache
functions") may lead to unearthing some of the alignment bugs we have:

These bugs were already there: If a DMA buffer is misaligned and you do
cache maintenance on it, you will corrupt memory that's unlucky to share
the cache line. This has been the case for many years though, which I
think is because that corruption was limited to the driver itself:
If a driver invalidates only part of its buffer, then that is its
problem and that of its consumers (e.g. TFTP failing for some file
names, because network driver only invalidated part of the packet).

When we start correctly invalidating the whole buffer though,
invalidaing misaligned buffers will lead us to possibly corrupt other
allocations after it, which makes the problem less localized.

Anyhow, the fix is correct and I spent some time going through all our
allocations to check whether they adhere to the DMA API. Having some way
to encode this into the type system would be nice for the future (maybe
something via named address spaces[1]), but for now I took the laborious
way of grepping for all /alloc/, /dma_map_single/ and /dma_sync_for/ we
have and checking them by hand.

I intend to document our expectation around the DMA API soon, but for
now, with this series applied our expectations are as follows:

 - Streaming DMA is only permissible with suitably aligned buffers,
   e.g. those allocated with dma_alloc()

 - DMA to stack needs to be eradicated. We currently seem to do this
   in three places still: HABv4, Raspberry Pi mailbox and some Virt I/O

 - "User" code should not need to call dma_alloc(). Buffers passed
   to read/write or cdev_read/cdev_write should be able to have
   arbitrary alignment. We could add a future "zero-copy" way, but
   currently drivers either use bounce buffers (e.g. RAW NAND with
   Denali, CAAM crypto or qemu_fw_cfg) or intermediate layers handle it
   (e.g.  block cache for MMC, ATA, NVMe), so user code need not worry.

 - USB buffers and Network packets should always be allocated with
   dma_alloc (or net_alloc_packet). No exceptions.

 - Especially network drivers must call dma_map_single on receive buffers
   once allocated and before bringing up the interface. Otherwise we have
   a race between CPU cache and device DMA. This applies to other users
   as well, but not observing it is less problematic, because e.g. MMC
   reads are synchronous while NIC RX is async.

 - Kernel code often does DMA to buffers allocated with kmalloc and
   friends. kmalloc now calls dma_alloc instead of normal malloc to
   maintain kernel compatibility.

Tested on top of master on STM32MP1 (MC-1), AM335 (Beaglebone Black),
BCM2711 (Raspberry Pi 4 32-bit), BCM2835 (Raspberry Pi 3 32-bit),
i.MX6 (RIoT-Board), RK3568 (Rock 3A), i.MX8MP (TQMA8MPXL) and
i.MX8MN (EVK).

[1]: SO/IEC JTC1 SC22 WG14 N1275

Ahmad Fatoum (23):
  habv4: use DMA-capable memory for getting event from BootROM
  dma: give inline dma_alloc a single external definition
  dma: add definition for dma_zalloc
  include: linux/kernel.h: factor out alignment macros
  driver: move out struct device definition into its own header
  dma: remove common.h include from asm/dma.h
  RISC-V: dma: fix dma.h inclusion
  sandbox: dma: drop unused driver.h include
  dma: remove linux/kernel.h dependency from dma.h
  include: linux/slab: fix possible overflow in kmalloc_array
  include: linux/slab: use dma_alloc for kmalloc
  include: linux/slab: retire krealloc
  commands: mmc_extcsd: use DMA capable memory where needed
  net: macb: use DMA-capable memory for receive buffer
  firmware: qemu_fw_cfg: use bounce buffer for write
  net: usb: asix: use dma_alloc for buffers in USB control messages
  net: usb: smsc95xx: use DMA memory for usb_control_msg
  usb: hub: use DMA memory in usb_get_port_status
  usb: hub: use DMA-capable memory in usb_hub_configure
  treewide: use new dma_zalloc instead of opencoding
  usb: dwc2: host: fix mismatch between dma_map_single and unmap
  net: bcmgenet: map DMA buffers with dma_map_single
  dma: debug: add alignment check when mapping buffers

 arch/arm/include/asm/dma.h               |   5 +-
 arch/kvx/include/asm/dma.h               |   4 +-
 arch/mips/include/asm/dma.h              |   3 +-
 arch/mips/lib/dma-default.c              |   1 +
 arch/riscv/cpu/dma.c                     |   2 +-
 arch/riscv/include/asm/dma.h             |   2 -
 arch/sandbox/include/asm/dma.h           |   1 -
 commands/mmc_extcsd.c                    |   4 +-
 drivers/dma/debug.c                      |   5 +
 drivers/dma/map.c                        |  17 ++++
 drivers/firmware/qemu_fw_cfg.c           |  20 +++-
 drivers/hab/habv4.c                      |   3 +-
 drivers/net/bcmgenet.c                   |  13 +--
 drivers/net/fsl-fman.c                   |   4 +-
 drivers/net/macb.c                       |   4 +-
 drivers/net/usb/asix.c                   |   8 +-
 drivers/net/usb/smsc95xx.c               |  15 ++-
 drivers/soc/starfive/jh7100_dma.c        |   2 +-
 drivers/usb/core/hub.c                   |  49 ++++++----
 drivers/usb/dwc2/host.c                  |   4 +-
 drivers/usb/gadget/function/f_fastboot.c |   3 +-
 drivers/video/mipi_dbi.c                 |   3 +-
 fs/ext4/ext4_common.h                    |  10 +-
 include/device.h                         | 111 +++++++++++++++++++++++
 include/dma.h                            |  16 +++-
 include/driver.h                         |  93 +------------------
 include/linux/align.h                    |  13 +++
 include/linux/device.h                   |   2 -
 include/linux/kernel.h                   |   9 +-
 include/linux/pagemap.h                  |   2 +-
 include/linux/slab.h                     |  20 ++--
 lib/kasan/test_kasan.c                   |   4 +-
 32 files changed, 266 insertions(+), 186 deletions(-)
 create mode 100644 include/device.h
 create mode 100644 include/linux/align.h

-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 01/23] habv4: use DMA-capable memory for getting event from BootROM
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 02/23] dma: give inline dma_alloc a single external definition Ahmad Fatoum
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We pass the buffer to the BootROM and we aren't sure yet whether this
requires us to do cache maintenance[1].

Anyhow, it's a tiny bit better to at least have cache line alignment for
data exchanged with TF-A and the BootROM, so do that.

[1]: https://lists.trustedfirmware.org/archives/list/tf-a@lists.trustedfirmware.org/message/D3PIAW7G2B3JQIH5BGMUZZKHPGNMXUUT/

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/hab/habv4.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hab/habv4.c b/drivers/hab/habv4.c
index a1d823ed2512..0f5618116e22 100644
--- a/drivers/hab/habv4.c
+++ b/drivers/hab/habv4.c
@@ -12,6 +12,7 @@
 #include <init.h>
 #include <types.h>
 #include <mmu.h>
+#include <dma.h>
 #include <zero_page.h>
 #include <linux/sizes.h>
 #include <linux/arm-smccc.h>
@@ -581,7 +582,7 @@ static uint8_t *hab_get_event(const struct habv4_rvt *rvt, int index, size_t *le
 	if (err != HAB_STATUS_SUCCESS)
 		return NULL;
 
-	buf = malloc(*len);
+	buf = dma_alloc(*len);
 	if (!buf)
 		return NULL;
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 02/23] dma: give inline dma_alloc a single external definition
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 01/23] habv4: use DMA-capable memory for getting event from BootROM Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 03/23] dma: add definition for dma_zalloc Ahmad Fatoum
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We'll be adding more calls to dma_alloc shortly, so move it
out-of-line.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/dma/map.c | 5 +++++
 include/dma.h     | 6 +++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/map.c b/drivers/dma/map.c
index ab86a8c7b139..ed7d3b68ffb1 100644
--- a/drivers/dma/map.c
+++ b/drivers/dma/map.c
@@ -2,6 +2,11 @@
 #include <dma.h>
 #include "debug.h"
 
+void *dma_alloc(size_t size)
+{
+	return xmemalign(DMA_ALIGNMENT, ALIGN(size, DMA_ALIGNMENT));
+}
+
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t address,
 			     size_t size, enum dma_data_direction dir)
 {
diff --git a/include/dma.h b/include/dma.h
index df9807b4f2e4..0b77949eaf05 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -21,10 +21,14 @@
 #define DMA_ALIGNMENT	32
 #endif
 
+#ifdef CONFIG_HAS_DMA
+void *dma_alloc(size_t size);
+#else
 static inline void *dma_alloc(size_t size)
 {
-	return xmemalign(DMA_ALIGNMENT, ALIGN(size, DMA_ALIGNMENT));
+	return malloc(size);
 }
+#endif
 
 static inline void dma_free(void *mem)
 {
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 03/23] dma: add definition for dma_zalloc
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 01/23] habv4: use DMA-capable memory for getting event from BootROM Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 02/23] dma: give inline dma_alloc a single external definition Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 04/23] include: linux/kernel.h: factor out alignment macros Ahmad Fatoum
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

For use by functions that want a zeroed buffer for DMA use, implement
dma_zalloc(). Having this in a single place instead of open-coding makes
it easier in future to possibly optimize zeroing of the buffer and makes
follow-up changes more concise.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/dma/map.c | 11 +++++++++++
 include/dma.h     |  6 ++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/dma/map.c b/drivers/dma/map.c
index ed7d3b68ffb1..e2656a27f183 100644
--- a/drivers/dma/map.c
+++ b/drivers/dma/map.c
@@ -7,6 +7,17 @@ void *dma_alloc(size_t size)
 	return xmemalign(DMA_ALIGNMENT, ALIGN(size, DMA_ALIGNMENT));
 }
 
+void *dma_zalloc(size_t size)
+{
+	void *buf;
+
+	buf = dma_alloc(size);
+	if (buf)
+		memset(buf, 0x00, size);
+
+	return buf;
+}
+
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t address,
 			     size_t size, enum dma_data_direction dir)
 {
diff --git a/include/dma.h b/include/dma.h
index 0b77949eaf05..a69072280bd5 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -23,11 +23,17 @@
 
 #ifdef CONFIG_HAS_DMA
 void *dma_alloc(size_t size);
+void *dma_zalloc(size_t size);
 #else
 static inline void *dma_alloc(size_t size)
 {
 	return malloc(size);
 }
+
+static inline void *dma_zalloc(size_t size)
+{
+	return calloc(size, 1);
+}
 #endif
 
 static inline void dma_free(void *mem)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 04/23] include: linux/kernel.h: factor out alignment macros
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 03/23] dma: add definition for dma_zalloc Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 05/23] driver: move out struct device definition into its own header Ahmad Fatoum
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

Linux has already factored these macros into a separate <linux/align.h>.
We now do the same for barebox to avoid a recursive dependency in
incoming patches via linux/pagemap.h, which just needs the align macros
and nothing else out of linux/kernel.h.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/align.h   | 13 +++++++++++++
 include/linux/kernel.h  |  9 +--------
 include/linux/pagemap.h |  2 +-
 3 files changed, 15 insertions(+), 9 deletions(-)
 create mode 100644 include/linux/align.h

diff --git a/include/linux/align.h b/include/linux/align.h
new file mode 100644
index 000000000000..8df1b3dcd749
--- /dev/null
+++ b/include/linux/align.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_ALIGN_H
+#define _LINUX_ALIGN_H
+
+#define ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a) - 1)
+#define ALIGN_DOWN(x, a)	ALIGN((x) - ((a) - 1), (a))
+#define __ALIGN_MASK(x, mask)	(((x) + (mask)) & ~(mask))
+#define PTR_ALIGN(p, a)		((typeof(p))ALIGN((unsigned long)(p), (a)))
+#define PTR_ALIGN_DOWN(p, a)	((typeof(p))ALIGN_DOWN((unsigned long)(p), (a)))
+#define PTR_IS_ALIGNED(x, a)	IS_ALIGNED((unsigned long)(x), (a))
+#define IS_ALIGNED(x, a)		(((x) & ((typeof(x))(a) - 1)) == 0)
+
+#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4e50f6075189..c411ac0860dd 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -10,6 +10,7 @@
 #include <linux/container_of.h>
 #include <linux/instruction_pointer.h>
 #include <linux/minmax.h>
+#include <linux/align.h>
 
 /**
  * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
@@ -19,14 +20,6 @@
  */
 #define REPEAT_BYTE(x)	((~0ul / 0xff) * (x))
 
-#define ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a) - 1)
-#define ALIGN_DOWN(x, a)	ALIGN((x) - ((a) - 1), (a))
-#define __ALIGN_MASK(x, mask)	(((x) + (mask)) & ~(mask))
-#define PTR_ALIGN(p, a)		((typeof(p))ALIGN((unsigned long)(p), (a)))
-#define PTR_ALIGN_DOWN(p, a)	((typeof(p))ALIGN_DOWN((unsigned long)(p), (a)))
-#define PTR_IS_ALIGNED(x, a)	IS_ALIGNED((unsigned long)(x), (a))
-#define IS_ALIGNED(x, a)		(((x) & ((typeof(x))(a) - 1)) == 0)
-
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 #define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
 
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0db192e4d3ab..8bdaff4ebf1b 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -3,7 +3,7 @@
 #ifndef _LINUX_PAGEMAP_H
 #define _LINUX_PAGEMAP_H
 
-#include <linux/kernel.h>
+#include <linux/align.h>
 
 /*
  * Copyright 1995 Linus Torvalds
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 05/23] driver: move out struct device definition into its own header
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 04/23] include: linux/kernel.h: factor out alignment macros Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 06/23] dma: remove common.h include from asm/dma.h Ahmad Fatoum
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

<driver.h> got so big that it can introduce issues with recursive
inclusion. Let's start breaking it up by moving the struct device
definition into a new device.h header.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/device.h | 111 +++++++++++++++++++++++++++++++++++++++++++++++
 include/driver.h |  93 +--------------------------------------
 2 files changed, 112 insertions(+), 92 deletions(-)
 create mode 100644 include/device.h

diff --git a/include/device.h b/include/device.h
new file mode 100644
index 000000000000..8c3561e5a2f6
--- /dev/null
+++ b/include/device.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * (C) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ */
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include <linux/types.h>
+
+enum dev_dma_coherence {
+	DEV_DMA_COHERENCE_DEFAULT = 0,
+	DEV_DMA_COHERENT,
+	DEV_DMA_NON_COHERENT,
+};
+
+struct device;
+struct bus_type;
+struct resource;
+struct driver;
+struct generic_pm_domain;
+struct platform_device_id;
+struct of_device_id;
+
+/** @brief Describes a particular device present in the system */
+struct device {
+	/*! This member (and 'type' described below) is used to match
+	 * with a driver. This is a descriptive name and could be
+	 * MPC5XXX_ether or imx_serial. Unless absolutely necessary,
+	 * should not be modified directly and dev_set_name() should
+	 * be used instead.
+	 */
+	char *name;
+
+	/*! This member is used to store device's unique name as
+	 *  obtained by calling dev_id(). Internal field, do not
+	 *  access it directly.
+	  */
+	char *unique_name;
+	/*! The id is used to uniquely identify a device in the system. The id
+	 * will show up under /dev/ as the device's name. Usually this is
+	 * something like eth0 or nor0. */
+	int id;
+
+	enum dev_dma_coherence dma_coherent;
+
+	struct resource *resource;
+	int num_resources;
+
+	void *platform_data; /*! board specific information about this device */
+
+	/*! Devices of a particular class normaly need to store more
+	 * information than struct device holds.
+	 */
+	void *priv;
+	void *type_data;     /*! In case this device is a specific device, this pointer
+			      * points to the type specific device, i.e. eth_device
+			      */
+	struct driver *driver; /*! The driver for this device */
+
+	struct list_head list;     /* The list of all devices */
+	struct list_head bus_list; /* our bus            */
+	struct list_head children; /* our children            */
+	struct list_head sibling;
+	struct list_head active;   /* The list of all devices which have a driver */
+
+	struct device *parent;   /* our parent, NULL if not present */
+
+	struct generic_pm_domain *pm_domain;	/* attached power domain */
+
+	struct bus_type *bus;
+
+	/*! The parameters for this device. This is used to carry information
+	 * of board specific data from the board code to the device driver. */
+	struct list_head parameters;
+
+	struct list_head cdevs;
+
+	const struct platform_device_id *id_entry;
+	union {
+		struct device_node *device_node;
+		struct device_node *of_node;
+	};
+
+	const struct of_device_id *of_id_entry;
+
+	u64 dma_mask;
+
+	unsigned long dma_offset;
+
+	void    (*info) (struct device *);
+	/*
+	 * For devices which take longer to probe this is called
+	 * when the driver should actually detect client devices
+	 */
+	int     (*detect) (struct device *);
+	void	(*rescan) (struct device *);
+
+	/*
+	 * if a driver probe is deferred, this stores the last error
+	 */
+	char *deferred_probe_reason;
+};
+
+struct device_alias {
+	struct device *dev;
+	struct list_head list;
+	char name[];
+};
+
+#endif
diff --git a/include/driver.h b/include/driver.h
index e02815d09b76..066e632134a1 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -10,6 +10,7 @@
 #include <linux/ioport.h>
 #include <linux/uuid.h>
 #include <linux/printk.h>
+#include <device.h>
 #include <of.h>
 #include <init.h>
 #include <filetype.h>
@@ -27,98 +28,6 @@ struct platform_device_id {
 	unsigned long driver_data;
 };
 
-enum dev_dma_coherence {
-	DEV_DMA_COHERENCE_DEFAULT = 0,
-	DEV_DMA_COHERENT,
-	DEV_DMA_NON_COHERENT,
-};
-
-/** @brief Describes a particular device present in the system */
-struct device {
-	/*! This member (and 'type' described below) is used to match
-	 * with a driver. This is a descriptive name and could be
-	 * MPC5XXX_ether or imx_serial. Unless absolutely necessary,
-	 * should not be modified directly and dev_set_name() should
-	 * be used instead.
-	 */
-	char *name;
-
-	/*! This member is used to store device's unique name as
-	 *  obtained by calling dev_id(). Internal field, do not
-	 *  access it directly.
-	  */
-	char *unique_name;
-	/*! The id is used to uniquely identify a device in the system. The id
-	 * will show up under /dev/ as the device's name. Usually this is
-	 * something like eth0 or nor0. */
-	int id;
-
-	enum dev_dma_coherence dma_coherent;
-
-	struct resource *resource;
-	int num_resources;
-
-	void *platform_data; /*! board specific information about this device */
-
-	/*! Devices of a particular class normaly need to store more
-	 * information than struct device holds.
-	 */
-	void *priv;
-	void *type_data;     /*! In case this device is a specific device, this pointer
-			      * points to the type specific device, i.e. eth_device
-			      */
-	struct driver *driver; /*! The driver for this device */
-
-	struct list_head list;     /* The list of all devices */
-	struct list_head bus_list; /* our bus            */
-	struct list_head children; /* our children            */
-	struct list_head sibling;
-	struct list_head active;   /* The list of all devices which have a driver */
-
-	struct device *parent;   /* our parent, NULL if not present */
-
-	struct generic_pm_domain *pm_domain;	/* attached power domain */
-
-	struct bus_type *bus;
-
-	/*! The parameters for this device. This is used to carry information
-	 * of board specific data from the board code to the device driver. */
-	struct list_head parameters;
-
-	struct list_head cdevs;
-
-	const struct platform_device_id *id_entry;
-	union {
-		struct device_node *device_node;
-		struct device_node *of_node;
-	};
-
-	const struct of_device_id *of_id_entry;
-
-	u64 dma_mask;
-
-	unsigned long dma_offset;
-
-	void    (*info) (struct device *);
-	/*
-	 * For devices which take longer to probe this is called
-	 * when the driver should actually detect client devices
-	 */
-	int     (*detect) (struct device *);
-	void	(*rescan) (struct device *);
-
-	/*
-	 * if a driver probe is deferred, this stores the last error
-	 */
-	char *deferred_probe_reason;
-};
-
-struct device_alias {
-	struct device *dev;
-	struct list_head list;
-	char name[];
-};
-
 /** @brief Describes a driver present in the system */
 struct driver {
 	/*! The name of this driver. Used to match to
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 06/23] dma: remove common.h include from asm/dma.h
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 05/23] driver: move out struct device definition into its own header Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 07/23] RISC-V: dma: fix dma.h inclusion Ahmad Fatoum
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

<common.h> inclusion will lead to a recursive inclusion with incoming
changes, so avoid that by using the headers that are actually needed.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/include/asm/dma.h  | 5 ++++-
 arch/kvx/include/asm/dma.h  | 4 +++-
 arch/mips/include/asm/dma.h | 3 ++-
 arch/mips/lib/dma-default.c | 1 +
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 0774a11c5a30..d045f00c67cf 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -1,7 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-FileCopyrightText: 2012 Marc Kleine-Budde <mkl@pengutronix.de> */
 
-#include <common.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <xfuncs.h>
+#include <malloc.h>
 
 #define DMA_ALIGNMENT	64
 
diff --git a/arch/kvx/include/asm/dma.h b/arch/kvx/include/asm/dma.h
index c6f67e76d024..f1b54afe25f5 100644
--- a/arch/kvx/include/asm/dma.h
+++ b/arch/kvx/include/asm/dma.h
@@ -4,7 +4,9 @@
 #ifndef __ASM_DMA_H
 #define __ASM_DMA_H
 
-#include <common.h>
+#include <linux/types.h>
+#include <linux/build_bug.h>
+#include <malloc.h>
 
 #define DMA_ALIGNMENT	64
 
diff --git a/arch/mips/include/asm/dma.h b/arch/mips/include/asm/dma.h
index 5c5b6d5b3a58..dbcbfa40768d 100644
--- a/arch/mips/include/asm/dma.h
+++ b/arch/mips/include/asm/dma.h
@@ -6,7 +6,8 @@
 #ifndef __ASM_DMA_H
 #define __ASM_DMA_H
 
-#include <common.h>
+#include <linux/pagemap.h>
+#include <linux/types.h>
 #include <malloc.h>
 #include <xfuncs.h>
 #include <asm/addrspace.h>
diff --git a/arch/mips/lib/dma-default.c b/arch/mips/lib/dma-default.c
index 54e66654687f..74aa8af55c45 100644
--- a/arch/mips/lib/dma-default.c
+++ b/arch/mips/lib/dma-default.c
@@ -4,6 +4,7 @@
  */
 
 #include <dma.h>
+#include <linux/bug.h>
 #include <asm/io.h>
 
 void arch_sync_dma_for_cpu(void *vaddr, size_t size,
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 07/23] RISC-V: dma: fix dma.h inclusion
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 06/23] dma: remove common.h include from asm/dma.h Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 08/23] sandbox: dma: drop unused driver.h include Ahmad Fatoum
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

dma.h include <asm/dma.h> first thing, so including <dma.h> from
<asm/dma.h> is pointless and using <asm/dma.h> directly is wrong.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/riscv/cpu/dma.c              | 2 +-
 arch/riscv/include/asm/dma.h      | 2 --
 drivers/soc/starfive/jh7100_dma.c | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/cpu/dma.c b/arch/riscv/cpu/dma.c
index 511170aaa4e2..f3a1a8ec9ac5 100644
--- a/arch/riscv/cpu/dma.c
+++ b/arch/riscv/cpu/dma.c
@@ -2,7 +2,7 @@
 
 #include <common.h>
 #include <xfuncs.h>
-#include <asm/dma.h>
+#include <dma.h>
 #include <malloc.h>
 
 static void __dma_flush_range(dma_addr_t start, dma_addr_t end)
diff --git a/arch/riscv/include/asm/dma.h b/arch/riscv/include/asm/dma.h
index 56bcf06cc4af..e1829d8c9613 100644
--- a/arch/riscv/include/asm/dma.h
+++ b/arch/riscv/include/asm/dma.h
@@ -17,6 +17,4 @@ void dma_set_ops(const struct dma_ops *ops);
 
 #define DMA_ALIGNMENT 64
 
-#include <dma.h>
-
 #endif /* _ASM_DMA_MAPPING_H */
diff --git a/drivers/soc/starfive/jh7100_dma.c b/drivers/soc/starfive/jh7100_dma.c
index e3cfc8cf6534..5f6e78fc3632 100644
--- a/drivers/soc/starfive/jh7100_dma.c
+++ b/drivers/soc/starfive/jh7100_dma.c
@@ -4,7 +4,7 @@
  */
 
 #include <common.h>
-#include <asm/dma.h>
+#include <dma.h>
 #include <soc/sifive/l2_cache.h>
 
 #define SDRAM_CACHED_BASE	0x80000000
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 08/23] sandbox: dma: drop unused driver.h include
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (6 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 07/23] RISC-V: dma: fix dma.h inclusion Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 09/23] dma: remove linux/kernel.h dependency from dma.h Ahmad Fatoum
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We don't require anything out of this header, so drop it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/sandbox/include/asm/dma.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/sandbox/include/asm/dma.h b/arch/sandbox/include/asm/dma.h
index cafbb7fe6a4c..ab84166846a2 100644
--- a/arch/sandbox/include/asm/dma.h
+++ b/arch/sandbox/include/asm/dma.h
@@ -10,7 +10,6 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <driver.h>
 
 #define DMA_ALIGNMENT	64
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 09/23] dma: remove linux/kernel.h dependency from dma.h
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (7 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 08/23] sandbox: dma: drop unused driver.h include Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 10/23] include: linux/slab: fix possible overflow in kmalloc_array Ahmad Fatoum
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

To prepare having linux/kernel.h transitively depend on dma.h, remove
dependency of dma.h on linux/kernel.h.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/dma/debug.c | 1 +
 drivers/dma/map.c   | 1 +
 include/dma.h       | 4 ++--
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/debug.c b/drivers/dma/debug.c
index e524dc4127ce..f4272e8f5822 100644
--- a/drivers/dma/debug.c
+++ b/drivers/dma/debug.c
@@ -2,6 +2,7 @@
 
 #include <dma.h>
 #include <linux/list.h>
+#include <linux/printk.h>
 #include "debug.h"
 
 static LIST_HEAD(dma_mappings);
diff --git a/drivers/dma/map.c b/drivers/dma/map.c
index e2656a27f183..cd0f5c3d3497 100644
--- a/drivers/dma/map.c
+++ b/drivers/dma/map.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <dma.h>
+#include <driver.h>
 #include "debug.h"
 
 void *dma_alloc(size_t size)
diff --git a/include/dma.h b/include/dma.h
index a69072280bd5..4fcd114bb6b5 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -8,12 +8,12 @@
 
 #include <malloc.h>
 #include <xfuncs.h>
-#include <linux/kernel.h>
+#include <linux/align.h>
 
 #include <dma-dir.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <driver.h>
+#include <device.h>
 
 #define DMA_ADDRESS_BROKEN	NULL
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 10/23] include: linux/slab: fix possible overflow in kmalloc_array
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (8 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 09/23] dma: remove linux/kernel.h dependency from dma.h Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 11/23] include: linux/slab: use dma_alloc for kmalloc Ahmad Fatoum
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

If we are unlucky, n * size would overflow size_t and we'll instead
allocate a small truncated value, which may lead to memory corruption.

Fix this by using size_mul, which saturates at SIZE_MAX.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/slab.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index dc80808938f4..36b93bdd2f1b 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -4,6 +4,7 @@
 #define _LINUX_SLAB_H
 
 #include <malloc.h>
+#include <linux/overflow.h>
 #include <linux/string.h>
 
 #define SLAB_CONSISTENCY_CHECKS	0
@@ -98,7 +99,7 @@ static inline void *kzalloc(size_t size, gfp_t flags)
  */
 static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
 {
-	return kmalloc(n * size, flags);
+	return kmalloc(size_mul(n, size), flags);
 }
 
 static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 11/23] include: linux/slab: use dma_alloc for kmalloc
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (9 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 10/23] include: linux/slab: fix possible overflow in kmalloc_array Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 12/23] include: linux/slab: retire krealloc Ahmad Fatoum
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

Linux kmalloc() family of function is suitable for use with streaming
DMA. barebox malloc() isn't though and changing that would increase the
alignment of all allocations.

Let's leave barebox malloc() as-is for now and have kmalloc/kcalloc and
friends allocate memory suitable for DMA as in Linux.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/slab.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 36b93bdd2f1b..47b0aec7e3b8 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -3,7 +3,7 @@
 #ifndef _LINUX_SLAB_H
 #define _LINUX_SLAB_H
 
-#include <malloc.h>
+#include <dma.h>
 #include <linux/overflow.h>
 #include <linux/string.h>
 
@@ -33,7 +33,7 @@
 
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
-	return malloc(size);
+	return dma_alloc(size);
 }
 
 struct kmem_cache {
@@ -59,12 +59,12 @@ struct kmem_cache *kmem_cache_create(const char *name, unsigned int size,
 
 static inline void kmem_cache_destroy(struct kmem_cache *cache)
 {
-	free(cache);
+	dma_free(cache);
 }
 
 static inline void kfree(const void *mem)
 {
-	free((void *)mem);
+	dma_free((void *)mem);
 }
 
 static inline void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
@@ -88,7 +88,7 @@ static inline void kmem_cache_free(struct kmem_cache *cache, void *mem)
 
 static inline void *kzalloc(size_t size, gfp_t flags)
 {
-	return calloc(size, 1);
+	return dma_zalloc(size);
 }
 
 /**
@@ -104,7 +104,7 @@ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
 
 static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 {
-	return calloc(n, size);
+	return dma_zalloc(size_mul(n, size));
 }
 
 static inline void *krealloc(void *ptr, size_t size, gfp_t flags)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 12/23] include: linux/slab: retire krealloc
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (10 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 11/23] include: linux/slab: use dma_alloc for kmalloc Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 13/23] commands: mmc_extcsd: use DMA capable memory where needed Ahmad Fatoum
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We have no users of this function in-tree, so it doesn't make sense to
invest the work to make it DMA compatible at the present.

Therefore, let's just remove it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/device.h | 2 --
 include/linux/slab.h   | 5 -----
 lib/kasan/test_kasan.c | 4 ++--
 3 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/include/linux/device.h b/include/linux/device.h
index d892a9cb0ef5..66294910abb3 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -12,13 +12,11 @@
 #define __devm_wrapper(fn, dev, ...) ({ BUG_ON(!dev); fn(__VA_ARGS__); })
 
 #define devm_kmalloc(...)		__devm_wrapper(kmalloc, __VA_ARGS__)
-#define devm_krealloc(...)		__devm_wrapper(krealloc, __VA_ARGS__)
 #define devm_kvasprintf(...)		__devm_wrapper(kvasprintf, __VA_ARGS__)
 #define devm_kasprintf(...)		__devm_wrapper(kasprintf, __VA_ARGS__)
 #define devm_kzalloc(...)		__devm_wrapper(kzalloc, __VA_ARGS__)
 #define devm_kmalloc_array(...)		__devm_wrapper(kmalloc_array, __VA_ARGS__)
 #define devm_kcalloc(...)		__devm_wrapper(kcalloc, __VA_ARGS__)
-#define devm_krealloc_array(...)	__devm_wrapper(krealloc_array, __VA_ARGS__)
 #define devm_kfree(...)			__devm_wrapper(kfree, __VA_ARGS__)
 #define devm_kstrdup(...)		__devm_wrapper(kstrdup, __VA_ARGS__)
 #define devm_kstrdup_const(...)		__devm_wrapper(kstrdup_const, __VA_ARGS__)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 47b0aec7e3b8..eba3593d758a 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -107,11 +107,6 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 	return dma_zalloc(size_mul(n, size));
 }
 
-static inline void *krealloc(void *ptr, size_t size, gfp_t flags)
-{
-	return realloc(ptr, size);
-}
-
 static inline char *kstrdup(const char *str, gfp_t flags)
 {
 	return strdup(str);
diff --git a/lib/kasan/test_kasan.c b/lib/kasan/test_kasan.c
index a74251a6d9ad..bacc02b56e98 100644
--- a/lib/kasan/test_kasan.c
+++ b/lib/kasan/test_kasan.c
@@ -69,7 +69,7 @@ static noinline void malloc_oob_realloc_more(void)
 	size_t size1 = 17;
 	size_t size2 = 19;
 
-	pr_info("out-of-bounds after krealloc more\n");
+	pr_info("out-of-bounds after realloc more\n");
 	ptr1 = malloc(size1);
 	ptr2 = realloc(ptr1, size2);
 	if (!ptr1 || !ptr2) {
@@ -92,7 +92,7 @@ static noinline void malloc_oob_realloc_less(void)
 	size_t size1 = 17;
 	size_t size2 = 15;
 
-	pr_info("out-of-bounds after krealloc less\n");
+	pr_info("out-of-bounds after realloc less\n");
 	ptr1 = malloc(size1);
 	ptr2 = realloc(ptr1, size2);
 	if (!ptr1 || !ptr2) {
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 13/23] commands: mmc_extcsd: use DMA capable memory where needed
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (11 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 12/23] include: linux/slab: retire krealloc Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 14/23] net: macb: use DMA-capable memory for receive buffer Ahmad Fatoum
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

mci_send_ext_csd may do DMA directly to the passed in buffer. Therefore,
be sure to allocate the buffer with suitable alignment.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 commands/mmc_extcsd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c
index f67c48404a54..993a6dd12b23 100644
--- a/commands/mmc_extcsd.c
+++ b/commands/mmc_extcsd.c
@@ -2418,7 +2418,7 @@ static int do_mmc_extcsd(int argc, char *argv[])
 		retval = -ENOENT;
 		goto error;
 	}
-	dst = xmalloc(EXT_CSD_BLOCKSIZE);
+	dst = dma_alloc(EXT_CSD_BLOCKSIZE);
 
 	retval = mci_send_ext_csd(mci, dst);
 	if (retval != 0)
@@ -2473,7 +2473,7 @@ static int do_mmc_extcsd(int argc, char *argv[])
 			print_register_readable(dst, index);
 
 error_with_mem:
-	free(dst);
+	dma_free(dst);
 error:
 	return retval;
 }
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 14/23] net: macb: use DMA-capable memory for receive buffer
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (12 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 13/23] commands: mmc_extcsd: use DMA capable memory where needed Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 15/23] firmware: qemu_fw_cfg: use bounce buffer for write Ahmad Fatoum
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

The driver supports older MACB-compatible NICs as well as the newer
GEM-compatible NICs. Both use DMA, but the older MACB support failed to
allocate the single receive buffer with suitable alignment.

Use net_alloc_packet() to fix that.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/net/macb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index f5b2fa74dc23..bcad88f60e7a 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -910,7 +910,7 @@ static int macb_probe(struct device *dev)
 		macb->gem_q1_descs = dma_alloc_coherent(GEM_Q1_DESC_BYTES,
 				DMA_ADDRESS_BROKEN);
 
-	macb->rx_packet_buf = xmalloc(PKTSIZE);
+	macb->rx_packet_buf = net_alloc_packet();
 
 	macb_reset_hw(macb);
 	ncfgr = macb_mdc_clk_div(macb);
@@ -938,7 +938,7 @@ static void macb_remove(struct device *dev)
 
 	macb_halt(&macb->netdev);
 
-	free(macb->rx_packet_buf);
+	net_free_packet(macb->rx_packet_buf);
 }
 
 static const struct macb_config fu540_c000_config = {
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 15/23] firmware: qemu_fw_cfg: use bounce buffer for write
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (13 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 14/23] net: macb: use DMA-capable memory for receive buffer Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 16/23] net: usb: asix: use dma_alloc for buffers in USB control messages Ahmad Fatoum
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

qemu_fw_cfg seems to be the only cdev that expect DMA-aligned memory in
its write operation. We don't generally allocate buffers for read() with
dma_alloc though, so introduce a bounce buffer. The write callback is
only used once for initial configuration of the frame buffer device, so
the allocation won't be noticeable.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/firmware/qemu_fw_cfg.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 1ba81d1b5002..3f129a2c1e02 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -173,14 +173,24 @@ static ssize_t fw_cfg_write(struct cdev *cdev, const void *buf, size_t count,
 	struct fw_cfg *fw_cfg = to_fw_cfg(cdev);
 	struct device *dev = cdev->dev;
 	struct fw_cfg_dma __iomem *acc = fw_cfg->acc_virt;
+	void *dma_buf;
 	dma_addr_t mapping;
+	int ret = 0;
 
 	if (pos != 0)
 		return -EINVAL;
 
-	mapping = dma_map_single(dev, (void *)buf, count, DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, mapping))
-		return -EFAULT;
+	dma_buf = dma_alloc(count);
+	if (!dma_buf)
+		return -ENOMEM;
+
+	memcpy(dma_buf, buf, count);
+
+	mapping = dma_map_single(dev, dma_buf, count, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, mapping)) {
+		ret = -EFAULT;
+		goto free_buf;
+	}
 
 	fw_cfg->next_read_offset = 0;
 
@@ -195,8 +205,10 @@ static ssize_t fw_cfg_write(struct cdev *cdev, const void *buf, size_t count,
 		;
 
 	dma_unmap_single(dev, mapping, count, DMA_FROM_DEVICE);
+free_buf:
+	dma_free(dma_buf);
 
-	return count;
+	return ret ?: count;
 }
 
 static struct cdev_operations fw_cfg_ops = {
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 16/23] net: usb: asix: use dma_alloc for buffers in USB control messages
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (14 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 15/23] firmware: qemu_fw_cfg: use bounce buffer for write Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 17/23] net: usb: smsc95xx: use DMA memory for usb_control_msg Ahmad Fatoum
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

usb_control_msg() expects DMA-capable memory for its data parameter,
but so far we passed buffers that may not have the correct alignment.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/net/usb/asix.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 9d34beab0df3..8ee0bc85348f 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -175,7 +175,7 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 	dev_dbg(&dev->edev.dev, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
 		cmd, value, index, size);
 
-	buf = malloc(size);
+	buf = dma_alloc(size);
 	if (!buf)
 		goto out;
 
@@ -193,7 +193,7 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		memcpy(data, buf, size);
 	else if (err >= 0)
 		err = -EINVAL;
-	free(buf);
+	dma_free(buf);
 
 out:
 	return err;
@@ -209,7 +209,7 @@ static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		cmd, value, index, size);
 
 	if (data) {
-		buf = malloc(size);
+		buf = dma_alloc(size);
 		if (!buf)
 			goto out;
 		memcpy(buf, data, size);
@@ -225,7 +225,7 @@ static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		buf,
 		size,
 		USB_CTRL_SET_TIMEOUT);
-	free(buf);
+	dma_free(buf);
 
 out:
 	return err;
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 17/23] net: usb: smsc95xx: use DMA memory for usb_control_msg
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (15 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 16/23] net: usb: asix: use dma_alloc for buffers in USB control messages Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 18/23] usb: hub: use DMA memory in usb_get_port_status Ahmad Fatoum
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

Iti's not safe to call usb_control_msg() with data pointing to the
stack. For some reason, this didn't blow up in our faces yet, but let's
do it properly now: Use a bounce buffer allocated with dma_alloc.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/net/usb/smsc95xx.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index b6f81cfab825..8590f4dd86b2 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -47,23 +47,25 @@ struct smsc95xx_priv {
 	u32 mac_cr;
 	int use_tx_csum;
 	int use_rx_csum;
+	__le32 *iobuf;
 };
 
 static int turbo_mode = 0;
 
 static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
 {
+	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
 	int ret;
 
 	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 		USB_VENDOR_REQUEST_READ_REGISTER,
 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, data, 4, USB_CTRL_GET_TIMEOUT);
+		00, index, pdata->iobuf, 4, USB_CTRL_GET_TIMEOUT);
 
 	if (ret < 0)
 		netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index);
-
-	le32_to_cpus(data);
+	else
+		*data = le32_to_cpup(pdata->iobuf);
 
 	debug("%s: 0x%08x 0x%08x\n", __func__, index, *data);
 
@@ -72,14 +74,15 @@ static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
 
 static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data)
 {
+	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
 	int ret;
 
-	cpu_to_le32s(&data);
+	*pdata->iobuf = cpu_to_le32(data);
 
 	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
 		USB_VENDOR_REQUEST_WRITE_REGISTER,
 		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, &data, 4, USB_CTRL_SET_TIMEOUT);
+		00, index, pdata->iobuf, 4, USB_CTRL_SET_TIMEOUT);
 
 	if (ret < 0)
 		netdev_warn(dev->net, "Failed to write register index 0x%08x\n", index);
@@ -726,6 +729,8 @@ static int smsc95xx_bind(struct usbnet *dev)
 	pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE;
 	pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
 
+	pdata->iobuf = dma_alloc(4);
+
 	/* Init all registers */
 	ret = smsc95xx_reset(dev);
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 18/23] usb: hub: use DMA memory in usb_get_port_status
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (16 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 17/23] net: usb: smsc95xx: use DMA memory for usb_control_msg Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 19/23] usb: hub: use DMA-capable memory in usb_hub_configure Ahmad Fatoum
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

Depending on driver, the data parameter in usb_control_msg may be used
in DMA, so let's use a bounce buffer allocated with dma_alloc instead of
doing DMA to the stack.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/usb/core/hub.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 650af0e8845a..9776fd72a5a4 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -86,18 +86,25 @@ static int usb_get_hub_status(struct usb_device *dev, void *data)
 			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
 }
 
-static int usb_get_port_status(struct usb_device *dev, int port, void *data)
+static int usb_get_port_status(struct usb_device *dev, int port,
+			       struct usb_port_status *status)
 {
+	struct usb_port_status *data;
 	int ret;
 
+	data = dma_alloc(sizeof(*data));
+	if (!data)
+		return -ENOMEM;
+
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
 			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
 	if (ret < 0)
-		return ret;
+		goto out;
+
+	*status = *data;
 
 	if (!usb_hub_is_root_hub(dev) && usb_hub_is_superspeed(dev)) {
-		struct usb_port_status *status = data;
 		u16 tmp = status->wPortStatus & USB_SS_PORT_STAT_MASK;
 
 		if (status->wPortStatus & USB_SS_PORT_STAT_POWER)
@@ -109,6 +116,8 @@ static int usb_get_port_status(struct usb_device *dev, int port, void *data)
 		status->wPortStatus = tmp;
 	}
 
+out:
+	dma_free(data);
 	return ret;
 }
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 19/23] usb: hub: use DMA-capable memory in usb_hub_configure
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (17 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 18/23] usb: hub: use DMA memory in usb_get_port_status Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 20/23] treewide: use new dma_zalloc instead of opencoding Ahmad Fatoum
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

usb_hub_configure does a lot of control transfers to `buffer', a
stack-allocated variable. Switch it to a suitably aligned buffer
allocated with dma_alloc() instead.

The cleanup on error intentionally doesn't touch `hub'. Errors should
probably invalidate this, but that's out-of-scope for this DMA fix.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/usb/core/hub.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 9776fd72a5a4..bef428f7fbd3 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -443,12 +443,16 @@ static int usb_device_list_scan(void)
 
 static int usb_hub_configure(struct usb_device *dev)
 {
-	unsigned char buffer[USB_BUFSIZ], *bitmap;
+	unsigned char *buffer, *bitmap;
 	struct usb_hub_descriptor *descriptor;
 	struct usb_hub_status *hubsts;
 	int i, ret;
 	struct usb_hub_device *hub;
 
+	buffer = dma_alloc(USB_BUFSIZ);
+	if (!buffer)
+		return -ENOMEM;
+
 	hub = xzalloc(sizeof (*hub));
 	dev->hub = hub;
 
@@ -457,7 +461,8 @@ static int usb_hub_configure(struct usb_device *dev)
 	if (usb_get_hub_descriptor(dev, buffer, 4) < 0) {
 		dev_dbg(&dev->dev, "%s: failed to get hub " \
 				   "descriptor, giving up %lX\n", __func__, dev->status);
-		return -1;
+		ret = -1;
+		goto out;
 	}
 	descriptor = (struct usb_hub_descriptor *)buffer;
 
@@ -467,13 +472,15 @@ static int usb_hub_configure(struct usb_device *dev)
 		dev_dbg(&dev->dev, "%s: failed to get hub " \
 				"descriptor - too long: %d\n", __func__,
 				descriptor->bLength);
-		return -1;
+		ret = -1;
+		goto out;
 	}
 
 	if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) {
 		dev_dbg(&dev->dev, "%s: failed to get hub " \
 				"descriptor 2nd giving up %lX\n", __func__, dev->status);
-		return -1;
+		ret = -1;
+		goto out;
 	}
 	memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength);
 	/* adjust 16bit values */
@@ -589,13 +596,15 @@ static int usb_hub_configure(struct usb_device *dev)
 	if (sizeof(struct usb_hub_status) > USB_BUFSIZ) {
 		dev_dbg(&dev->dev, "%s: failed to get Status - " \
 				"too long: %d\n", __func__, descriptor->bLength);
-		return -1;
+		ret = -1;
+		goto out;
 	}
 
 	if (usb_get_hub_status(dev, buffer) < 0) {
 		dev_dbg(&dev->dev, "%s: failed to get Status %lX\n", __func__,
 				dev->status);
-		return -1;
+		ret = -1;
+		goto out;
 	}
 
 	hubsts = (struct usb_hub_status *)buffer;
@@ -610,16 +619,12 @@ static int usb_hub_configure(struct usb_device *dev)
 		"" : "no ");
 
 	if (dev->host->update_hub_device) {
-		int ret;
-
 		ret = dev->host->update_hub_device(dev);
 		if (ret)
-			return ret;
+			goto out;
 	}
 
 	if (!usb_hub_is_root_hub(dev) && usb_hub_is_superspeed(dev)) {
-		int ret;
-
 		/*
 		* This request sets the value that the hub uses to
 		* determine the index into the 'route string index'
@@ -629,13 +634,16 @@ static int usb_hub_configure(struct usb_device *dev)
 		if (ret < 0) {
 			dev_dbg(&dev->dev, "failed to set hub depth (0x%08lx)\n",
 				dev->status);
-			return ret;
+			goto out;
 		}
 	}
 
 	usb_hub_power_on(hub);
 
-	return 0;
+	ret = 0;
+out:
+	dma_free(buffer);
+	return ret;
 }
 
 static int usb_hub_configure_ports(struct usb_device *dev)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 20/23] treewide: use new dma_zalloc instead of opencoding
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (18 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 19/23] usb: hub: use DMA-capable memory in usb_hub_configure Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 21/23] usb: dwc2: host: fix mismatch between dma_map_single and unmap Ahmad Fatoum
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We got a number of places using dma_alloc and zeroing its contents.
Replace the ones found by a quick grep with the new dma_zalloc.

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/net/fsl-fman.c                   |  4 +---
 drivers/usb/gadget/function/f_fastboot.c |  3 +--
 drivers/video/mipi_dbi.c                 |  3 +--
 fs/ext4/ext4_common.h                    | 10 +---------
 4 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/fsl-fman.c b/drivers/net/fsl-fman.c
index 9ae4dc9abf70..5528ecccc950 100644
--- a/drivers/net/fsl-fman.c
+++ b/drivers/net/fsl-fman.c
@@ -616,9 +616,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth)
 		return -ENOMEM;
 
 	/* alloc Rx buffer from main memory */
-	rx_buf_pool = dma_alloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE);
-
-	memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE);
+	rx_buf_pool = dma_zalloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE);
 
 	/* save them to fm_eth */
 	fm_eth->rx_bd_ring = rx_bd_ring_base;
diff --git a/drivers/usb/gadget/function/f_fastboot.c b/drivers/usb/gadget/function/f_fastboot.c
index 41450268fcdb..30d257b5002a 100644
--- a/drivers/usb/gadget/function/f_fastboot.c
+++ b/drivers/usb/gadget/function/f_fastboot.c
@@ -199,12 +199,11 @@ static struct usb_request *fastboot_alloc_request(struct usb_ep *ep)
 		return NULL;
 
 	req->length = EP_BUFFER_SIZE;
-	req->buf = dma_alloc(EP_BUFFER_SIZE);
+	req->buf = dma_zalloc(EP_BUFFER_SIZE);
 	if (!req->buf) {
 		usb_ep_free_request(ep, req);
 		return NULL;
 	}
-	memset(req->buf, 0, EP_BUFFER_SIZE);
 
 	return req;
 }
diff --git a/drivers/video/mipi_dbi.c b/drivers/video/mipi_dbi.c
index 2f8d6ecc72cf..9611a402d1ba 100644
--- a/drivers/video/mipi_dbi.c
+++ b/drivers/video/mipi_dbi.c
@@ -398,8 +398,7 @@ int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, struct fb_ops *ops,
 	info->bits_per_pixel = 16;
 	info->line_length = info->xres * 2;
 	info->screen_size = info->line_length * info->yres;
-	info->screen_base = dma_alloc(info->screen_size);
-	memset(info->screen_base, 0, info->screen_size);
+	info->screen_base = dma_zalloc(info->screen_size);
 
 	info->red.length = 5;
 	info->red.offset = 11;
diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
index f8ebd7626636..3286a21c0e26 100644
--- a/fs/ext4/ext4_common.h
+++ b/fs/ext4/ext4_common.h
@@ -36,15 +36,7 @@
 #include "ext4fs.h"
 #include "ext_common.h"
 
-static inline void *zalloc(size_t size)
-{
-	void *p = dma_alloc(size);
-
-	if (p)
-		memset(p, 0, size);
-
-	return p;
-}
+#define zalloc	dma_zalloc
 
 int ext4fs_read_inode(struct ext2_data *data, int ino,
 		      struct ext2_inode *inode);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 21/23] usb: dwc2: host: fix mismatch between dma_map_single and unmap
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (19 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 20/23] treewide: use new dma_zalloc instead of opencoding Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 22/23] net: bcmgenet: map DMA buffers with dma_map_single Ahmad Fatoum
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

xfer_len is used as argument to dma_unmap_single, so changing it value
to one different from dma_map_single will have CONFIG_DMA_API_DEBUG
complain.

Besides the unmap, xfer_len is only used to compute *actual_len, so do
arithmetic only on that to fix the warning.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/usb/dwc2/host.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index 344f058be208..a9b25aeeaa11 100644
--- a/drivers/usb/dwc2/host.c
+++ b/drivers/usb/dwc2/host.c
@@ -209,9 +209,9 @@ static int transfer_chunk(struct dwc2 *dwc2, u8 hc,
 	if (ret < 0)
 		goto exit;
 
-	if (in)
-		xfer_len -= sub;
 	*actual_len = xfer_len;
+	if (in)
+		*actual_len -= sub;
 
 exit:
 	if (xfer_len)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 22/23] net: bcmgenet: map DMA buffers with dma_map_single
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (20 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 21/23] usb: dwc2: host: fix mismatch between dma_map_single and unmap Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-24  6:40 ` [PATCH master 23/23] dma: debug: add alignment check when mapping buffers Ahmad Fatoum
  2024-04-25  7:39 ` [PATCH master 00/23] treewide: fix bugs using DMA API Sascha Hauer
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

We need to map DMA buffers first before handing them off to HW,
otherwise dirty cache lines may get evicted in the time window
between HW conducting DMA to rx_buffer and dma_sync_single_for_cpu
invalidating the CPU cache leading to corrupted packets.

This was detected by CONFIG_DMA_API_DEBUG, but needed adding a manual
!dev check into debug_dma_sync_single_for_cpu/device to silence the
not-yet fixed reports about the Rpi mailbox driver.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
Cc: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
---
 drivers/net/bcmgenet.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bcmgenet.c b/drivers/net/bcmgenet.c
index 9e0bacb31adf..acbb973a92f2 100644
--- a/drivers/net/bcmgenet.c
+++ b/drivers/net/bcmgenet.c
@@ -356,12 +356,13 @@ static void rx_descs_init(struct bcmgenet_eth_priv *priv)
 	len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
 
 	for (i = 0; i < RX_DESCS; i++) {
-		writel(lower_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]),
-		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_LO);
-		writel(upper_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]),
-		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_HI);
-		writel(len_stat,
-		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_LENGTH_STATUS);
+		dma_addr_t dma_addr = dma_map_single(priv->dev, &rxbuffs[i * RX_BUF_LENGTH],
+			   RX_BUF_LENGTH, DMA_FROM_DEVICE);
+		void *desc = desc_base + i * DMA_DESC_SIZE;
+
+		writel(lower_32_bits(dma_addr), desc + DMA_DESC_ADDRESS_LO);
+		writel(upper_32_bits(dma_addr), desc + DMA_DESC_ADDRESS_HI);
+		writel(len_stat, desc + DMA_DESC_LENGTH_STATUS);
 	}
 }
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH master 23/23] dma: debug: add alignment check when mapping buffers
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (21 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 22/23] net: bcmgenet: map DMA buffers with dma_map_single Ahmad Fatoum
@ 2024-04-24  6:40 ` Ahmad Fatoum
  2024-04-25  7:39 ` [PATCH master 00/23] treewide: fix bugs using DMA API Sascha Hauer
  23 siblings, 0 replies; 25+ messages in thread
From: Ahmad Fatoum @ 2024-04-24  6:40 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Scholz, Ahmad Fatoum

dma_map_single should only be called on buffers that have suitable DMA
alignment, otherwise cache maintenance may corrupt adjacent memory due
the cache line granularity. Let's verify this is indeed the case at
runtime.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/dma/debug.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/dma/debug.c b/drivers/dma/debug.c
index f4272e8f5822..32a417504479 100644
--- a/drivers/dma/debug.c
+++ b/drivers/dma/debug.c
@@ -128,6 +128,10 @@ void debug_dma_map(struct device *dev, void *addr,
 	list_add(&entry->list, &dma_mappings);
 
 	dma_debug(entry, "allocated\n");
+
+	if (!IS_ALIGNED(dev_addr, DMA_ALIGNMENT))
+		dma_dev_warn(dev, "Mapping insufficiently aligned %s buffer 0x%llx+0x%zx: %u bytes required!\n",
+			     dir2name[direction], (u64)addr, size, DMA_ALIGNMENT);
 }
 
 void debug_dma_unmap(struct device *dev, dma_addr_t addr,
-- 
2.39.2




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH master 00/23] treewide: fix bugs using DMA API
  2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
                   ` (22 preceding siblings ...)
  2024-04-24  6:40 ` [PATCH master 23/23] dma: debug: add alignment check when mapping buffers Ahmad Fatoum
@ 2024-04-25  7:39 ` Sascha Hauer
  23 siblings, 0 replies; 25+ messages in thread
From: Sascha Hauer @ 2024-04-25  7:39 UTC (permalink / raw)
  To: barebox, Ahmad Fatoum; +Cc: Enrico Scholz


On Wed, 24 Apr 2024 08:40:35 +0200, Ahmad Fatoum wrote:
> As described in commi b986aad24ab8 ("mci: core: allocate memory used
> for DMA with dma_alloc"), the recent fix to ARMv8 cache operations in
> commit 65ef5d885263 ("ARM64: let 'end' point after the range in cache
> functions") may lead to unearthing some of the alignment bugs we have:
> 
> These bugs were already there: If a DMA buffer is misaligned and you do
> cache maintenance on it, you will corrupt memory that's unlucky to share
> the cache line. This has been the case for many years though, which I
> think is because that corruption was limited to the driver itself:
> If a driver invalidates only part of its buffer, then that is its
> problem and that of its consumers (e.g. TFTP failing for some file
> names, because network driver only invalidated part of the packet).
> 
> [...]

Applied, thanks!

[01/23] habv4: use DMA-capable memory for getting event from BootROM
        https://git.pengutronix.de/cgit/barebox/commit/?id=72b50532f7d9 (link may not be stable)
[02/23] dma: give inline dma_alloc a single external definition
        https://git.pengutronix.de/cgit/barebox/commit/?id=f77b139c4d74 (link may not be stable)
[03/23] dma: add definition for dma_zalloc
        https://git.pengutronix.de/cgit/barebox/commit/?id=d2d9eb85597c (link may not be stable)
[04/23] include: linux/kernel.h: factor out alignment macros
        https://git.pengutronix.de/cgit/barebox/commit/?id=04fbbf21e502 (link may not be stable)
[05/23] driver: move out struct device definition into its own header
        https://git.pengutronix.de/cgit/barebox/commit/?id=58e2ba922bea (link may not be stable)
[06/23] dma: remove common.h include from asm/dma.h
        https://git.pengutronix.de/cgit/barebox/commit/?id=d0124e06ab06 (link may not be stable)
[07/23] RISC-V: dma: fix dma.h inclusion
        https://git.pengutronix.de/cgit/barebox/commit/?id=a9e636c1b9d9 (link may not be stable)
[08/23] sandbox: dma: drop unused driver.h include
        https://git.pengutronix.de/cgit/barebox/commit/?id=d256efaaff68 (link may not be stable)
[09/23] dma: remove linux/kernel.h dependency from dma.h
        https://git.pengutronix.de/cgit/barebox/commit/?id=27490e48068c (link may not be stable)
[10/23] include: linux/slab: fix possible overflow in kmalloc_array
        https://git.pengutronix.de/cgit/barebox/commit/?id=f82819fb748a (link may not be stable)
[11/23] include: linux/slab: use dma_alloc for kmalloc
        https://git.pengutronix.de/cgit/barebox/commit/?id=9b12861830e0 (link may not be stable)
[12/23] include: linux/slab: retire krealloc
        https://git.pengutronix.de/cgit/barebox/commit/?id=3afbd2693d2f (link may not be stable)
[13/23] commands: mmc_extcsd: use DMA capable memory where needed
        https://git.pengutronix.de/cgit/barebox/commit/?id=9d320afb3df3 (link may not be stable)
[14/23] net: macb: use DMA-capable memory for receive buffer
        https://git.pengutronix.de/cgit/barebox/commit/?id=9ce5a4a7792b (link may not be stable)
[15/23] firmware: qemu_fw_cfg: use bounce buffer for write
        https://git.pengutronix.de/cgit/barebox/commit/?id=cf6a5d4321c9 (link may not be stable)
[16/23] net: usb: asix: use dma_alloc for buffers in USB control messages
        https://git.pengutronix.de/cgit/barebox/commit/?id=25826dced0d1 (link may not be stable)
[17/23] net: usb: smsc95xx: use DMA memory for usb_control_msg
        https://git.pengutronix.de/cgit/barebox/commit/?id=c7ce7c992ccd (link may not be stable)
[18/23] usb: hub: use DMA memory in usb_get_port_status
        https://git.pengutronix.de/cgit/barebox/commit/?id=3a678386fe77 (link may not be stable)
[19/23] usb: hub: use DMA-capable memory in usb_hub_configure
        https://git.pengutronix.de/cgit/barebox/commit/?id=7cffd374fbc3 (link may not be stable)
[20/23] treewide: use new dma_zalloc instead of opencoding
        https://git.pengutronix.de/cgit/barebox/commit/?id=f607c950a05e (link may not be stable)
[21/23] usb: dwc2: host: fix mismatch between dma_map_single and unmap
        https://git.pengutronix.de/cgit/barebox/commit/?id=a0ae1c2c67d7 (link may not be stable)
[22/23] net: bcmgenet: map DMA buffers with dma_map_single
        https://git.pengutronix.de/cgit/barebox/commit/?id=ecf47be780ce (link may not be stable)
[23/23] dma: debug: add alignment check when mapping buffers
        https://git.pengutronix.de/cgit/barebox/commit/?id=699194dd2a4f (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2024-04-25  7:40 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-24  6:40 [PATCH master 00/23] treewide: fix bugs using DMA API Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 01/23] habv4: use DMA-capable memory for getting event from BootROM Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 02/23] dma: give inline dma_alloc a single external definition Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 03/23] dma: add definition for dma_zalloc Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 04/23] include: linux/kernel.h: factor out alignment macros Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 05/23] driver: move out struct device definition into its own header Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 06/23] dma: remove common.h include from asm/dma.h Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 07/23] RISC-V: dma: fix dma.h inclusion Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 08/23] sandbox: dma: drop unused driver.h include Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 09/23] dma: remove linux/kernel.h dependency from dma.h Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 10/23] include: linux/slab: fix possible overflow in kmalloc_array Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 11/23] include: linux/slab: use dma_alloc for kmalloc Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 12/23] include: linux/slab: retire krealloc Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 13/23] commands: mmc_extcsd: use DMA capable memory where needed Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 14/23] net: macb: use DMA-capable memory for receive buffer Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 15/23] firmware: qemu_fw_cfg: use bounce buffer for write Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 16/23] net: usb: asix: use dma_alloc for buffers in USB control messages Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 17/23] net: usb: smsc95xx: use DMA memory for usb_control_msg Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 18/23] usb: hub: use DMA memory in usb_get_port_status Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 19/23] usb: hub: use DMA-capable memory in usb_hub_configure Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 20/23] treewide: use new dma_zalloc instead of opencoding Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 21/23] usb: dwc2: host: fix mismatch between dma_map_single and unmap Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 22/23] net: bcmgenet: map DMA buffers with dma_map_single Ahmad Fatoum
2024-04-24  6:40 ` [PATCH master 23/23] dma: debug: add alignment check when mapping buffers Ahmad Fatoum
2024-04-25  7:39 ` [PATCH master 00/23] treewide: fix bugs using DMA API Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox