summaryrefslogtreecommitdiffstats
path: root/include/sound/memalloc.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-09-14 22:12:34 -1000
committerTejun Heo <tj@kernel.org>2026-09-15 06:57:20 -1000
commita9e3760b0838299649c0d57cca44daaf40ba3c33 (patch)
tree95807ff0e511c05602ef34808cfc660303309057 /include/sound/memalloc.h
downloadlinux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.tar.gz
linux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.zip
sched_ext: Maintain an online cid mask in the scheduler arenagrafted
Schedulers on the default cid mapping treat [0, nr_online_cids) as the online set and restart on hotplug. Schedulers that install their own mapping with scx_bpf_cid_override() have no way to learn which cids are online: the count no longer identifies members and the CPU-form cpumask is unusable from cid programs. This is an obvious hole in the cid API. Add scx_bpf_online_cmask(), a kernel-maintained cmask in the scheduler's arena, allocated alongside the per-CPU scratch masks and populated after the cid mapping is finalized and before ops.init(), for child schedulers too. The pointer stays valid through ops.exit() with no reference to take. It is the arena offset as a void pointer, the same form struct_ops arena arguments arrive in. The verifier types the void return as a scalar for the program's arena cast. The mask follows the SCX hotplug notifications: seeded from cpu_active_mask and updated before ops.cid_online/offline() runs, so it lags cpu_online_mask only inside a hotplug transition. Updates walk the scheduler list under the lock that also serializes unlinking. Reads are live, not atomic snapshots. Root initialization excludes hotplug. v2: Reworded the getter kerneldoc (Andrea Righi). Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
Diffstat (limited to 'include/sound/memalloc.h')
-rw-r--r--include/sound/memalloc.h120
1 files changed, 120 insertions, 0 deletions
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
new file mode 100644
index 000000000..9dd475cf4
--- /dev/null
+++ b/include/sound/memalloc.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ * Takashi Iwai <tiwai@suse.de>
+ *
+ * Generic memory allocators
+ */
+
+#ifndef __SOUND_MEMALLOC_H
+#define __SOUND_MEMALLOC_H
+
+#include <linux/dma-direction.h>
+#include <asm/page.h>
+
+struct device;
+struct vm_area_struct;
+struct sg_table;
+
+/*
+ * buffer device info
+ */
+struct snd_dma_device {
+ int type; /* SNDRV_DMA_TYPE_XXX */
+ enum dma_data_direction dir; /* DMA direction */
+ bool need_sync; /* explicit sync needed? */
+ struct device *dev; /* generic device */
+};
+
+/*
+ * buffer types
+ */
+#define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */
+#define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */
+#define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */
+#define SNDRV_DMA_TYPE_DEV_WC 5 /* continuous write-combined */
+#ifdef CONFIG_GENERIC_ALLOCATOR
+#define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */
+#else
+#define SNDRV_DMA_TYPE_DEV_IRAM SNDRV_DMA_TYPE_DEV
+#endif
+#define SNDRV_DMA_TYPE_VMALLOC 7 /* vmalloc'ed buffer */
+#define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */
+#define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */
+#ifdef CONFIG_SND_DMA_SGBUF
+#define SNDRV_DMA_TYPE_DEV_SG 3 /* S/G pages */
+#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
+#else
+#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
+#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
+#endif
+
+/*
+ * info for buffer allocation
+ */
+struct snd_dma_buffer {
+ struct snd_dma_device dev; /* device type */
+ unsigned char *area; /* virtual pointer */
+ dma_addr_t addr; /* physical address */
+ size_t bytes; /* buffer size in bytes */
+ void *private_data; /* private for allocator; don't touch */
+};
+
+/*
+ * return the pages matching with the given byte size
+ */
+static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
+{
+ return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
+/* allocate/release a buffer */
+int snd_dma_alloc_dir_pages(int type, struct device *dev,
+ enum dma_data_direction dir, size_t size,
+ struct snd_dma_buffer *dmab);
+
+static inline int snd_dma_alloc_pages(int type, struct device *dev,
+ size_t size, struct snd_dma_buffer *dmab)
+{
+ return snd_dma_alloc_dir_pages(type, dev, DMA_BIDIRECTIONAL, size, dmab);
+}
+
+int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
+ struct snd_dma_buffer *dmab);
+void snd_dma_free_pages(struct snd_dma_buffer *dmab);
+int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab,
+ struct vm_area_struct *area);
+
+enum snd_dma_sync_mode { SNDRV_DMA_SYNC_CPU, SNDRV_DMA_SYNC_DEVICE };
+#ifdef CONFIG_HAS_DMA
+void snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
+ enum snd_dma_sync_mode mode);
+#else
+static inline void snd_dma_buffer_sync(struct snd_dma_buffer *dmab,
+ enum snd_dma_sync_mode mode) {}
+#endif
+
+dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset);
+struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
+unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
+ unsigned int ofs, unsigned int size);
+
+/* device-managed memory allocator */
+struct snd_dma_buffer *snd_devm_alloc_dir_pages(struct device *dev, int type,
+ enum dma_data_direction dir,
+ size_t size);
+
+static inline struct snd_dma_buffer *
+snd_devm_alloc_pages(struct device *dev, int type, size_t size)
+{
+ return snd_devm_alloc_dir_pages(dev, type, DMA_BIDIRECTIONAL, size);
+}
+
+static inline struct sg_table *
+snd_dma_noncontig_sg_table(struct snd_dma_buffer *dmab)
+{
+ return dmab->private_data;
+}
+
+#endif /* __SOUND_MEMALLOC_H */
+