* [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again
@ 2022-08-21 8:22 Takashi Iwai
2022-08-21 11:48 ` kernel test robot
2022-08-21 14:31 ` kernel test robot
0 siblings, 2 replies; 3+ messages in thread
From: Takashi Iwai @ 2022-08-21 8:22 UTC (permalink / raw)
To: alsa-devel
We dropped the x86-specific hack for WC-page allocations with a hope
that the standard dma_alloc_wc() works nowadays. Alas, it doesn't,
and we need to take back some workaround again, but in a different
form, as the previous one was broken for some platforms.
This patch re-introduces the x86-specific WC-page allocations, but it
uses rather the manual page allocations instead of
dma_alloc_coherent(). The use of dma_alloc_coherent() was also a
potential problem in the recent addition of the fallback allocation
for noncontig pages, and this patch eliminates both at once.
Fixes: 9882d63bea14 ("ALSA: memalloc: Drop x86-specific hack for WC allocations")
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216363
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/memalloc.c | 87 +++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 16 deletions(-)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index d3885cb02270..90d74855d988 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -20,6 +20,13 @@
static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+ dma_addr_t *addr, bool wc);
+static void do_free_fallback_pages(void *p, size_t size, bool wc);
+static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
+#endif
+
/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
gfp_t default_gfp)
@@ -277,16 +284,21 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
/*
* Continuous pages allocator
*/
-static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *do_alloc_pages(size_t size, dma_addr_t *addr, unsigned long gfp)
{
- gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
void *p = alloc_pages_exact(size, gfp);
if (p)
- dmab->addr = page_to_phys(virt_to_page(p));
+ *addr = page_to_phys(virt_to_page(p));
return p;
}
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+ return do_alloc_pages(size, &dmab->addr,
+ snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
+}
+
static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
{
free_pages_exact(dmab->area, dmab->bytes);
@@ -463,6 +475,25 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
/*
* Write-combined pages
*/
+/* x86-specific allocations */
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+ return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+ do_free_fallback_pages(dmab->area, dmab->bytes, true);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+ struct vm_area_struct *area)
+{
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+ return snd_dma_continuous_mmap(dmab, area);
+}
+#else
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
@@ -479,6 +510,7 @@ static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
return dma_mmap_wc(dmab->dev.dev, area,
dmab->area, dmab->addr, dmab->bytes);
}
+#endif /* CONFIG_SND_DMA_SGBUF */
static const struct snd_malloc_ops snd_dma_wc_ops = {
.alloc = snd_dma_wc_alloc,
@@ -486,10 +518,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
.mmap = snd_dma_wc_mmap,
};
-#ifdef CONFIG_SND_DMA_SGBUF
-static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
-#endif
-
/*
* Non-contiguous pages allocator
*/
@@ -669,6 +697,37 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
};
+/* manual page allocations with wc setup */
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+ dma_addr_t *addr, bool wc)
+{
+ void *p;
+ unsigned long gfp = DEFAULT_GFP & ~__GFP_COMP;
+
+ again:
+ p = do_alloc_pages(size, addr, gfp);
+ if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
+ if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
+ gfp |= GFP_DMA32;
+ goto again;
+ }
+ if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
+ gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+ goto again;
+ }
+ }
+ if (p && wc)
+ set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
+ return p;
+}
+
+static void do_free_fallback_pages(void *p, size_t size, bool wc)
+{
+ if (wc)
+ set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
+ free_pages_exact(p, size);
+}
+
/* Fallback SG-buffer allocations for x86 */
struct snd_dma_sg_fallback {
size_t count;
@@ -679,14 +738,11 @@ struct snd_dma_sg_fallback {
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
struct snd_dma_sg_fallback *sgbuf)
{
+ bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
size_t i;
- if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
- set_pages_array_wb(sgbuf->pages, sgbuf->count);
for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
- dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
- page_address(sgbuf->pages[i]),
- sgbuf->addrs[i]);
+ do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
kvfree(sgbuf->pages);
kvfree(sgbuf->addrs);
kfree(sgbuf);
@@ -698,6 +754,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
struct page **pages;
size_t i, count;
void *p;
+ bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (!sgbuf)
@@ -712,15 +769,13 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
goto error;
for (i = 0; i < count; sgbuf->count++, i++) {
- p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
- &sgbuf->addrs[i], DEFAULT_GFP);
+ p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE,
+ &sgbuf->addrs[i], wc);
if (!p)
goto error;
sgbuf->pages[i] = virt_to_page(p);
}
- if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
- set_pages_array_wc(pages, count);
p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
if (!p)
goto error;
--
2.35.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again
2022-08-21 8:22 [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again Takashi Iwai
@ 2022-08-21 11:48 ` kernel test robot
2022-08-21 14:31 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2022-08-21 11:48 UTC (permalink / raw)
To: Takashi Iwai, alsa-devel; +Cc: kbuild-all
Hi Takashi,
I love your patch! Perhaps something to improve:
[auto build test WARNING on tiwai-sound/for-next]
[also build test WARNING on linus/master v6.0-rc1 next-20220819]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Takashi-Iwai/ALSA-memalloc-Revive-x86-specific-WC-page-allocations-again/20220821-162443
base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next
config: openrisc-randconfig-s052-20220821 (https://download.01.org/0day-ci/archive/20220821/202208211945.6Lmqeudy-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/86072b28544f52618e4ce8336ba80be1d67f38d9
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Takashi-Iwai/ALSA-memalloc-Revive-x86-specific-WC-page-allocations-again/20220821-162443
git checkout 86072b28544f52618e4ce8336ba80be1d67f38d9
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=openrisc SHELL=/bin/bash sound/core/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> sound/core/memalloc.c:289:43: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected restricted gfp_t [usertype] gfp_mask @@ got unsigned long gfp @@
sound/core/memalloc.c:289:43: sparse: expected restricted gfp_t [usertype] gfp_mask
sound/core/memalloc.c:289:43: sparse: got unsigned long gfp
>> sound/core/memalloc.c:299:52: sparse: sparse: incorrect type in argument 3 (different base types) @@ expected unsigned long gfp @@ got restricted gfp_t @@
sound/core/memalloc.c:299:52: sparse: expected unsigned long gfp
sound/core/memalloc.c:299:52: sparse: got restricted gfp_t
vim +289 sound/core/memalloc.c
37af81c5998f4b Takashi Iwai 2021-06-09 283
37af81c5998f4b Takashi Iwai 2021-06-09 284 /*
37af81c5998f4b Takashi Iwai 2021-06-09 285 * Continuous pages allocator
37af81c5998f4b Takashi Iwai 2021-06-09 286 */
86072b28544f52 Takashi Iwai 2022-08-21 287 static void *do_alloc_pages(size_t size, dma_addr_t *addr, unsigned long gfp)
37af81c5998f4b Takashi Iwai 2021-06-09 288 {
f84ba106a0185b Takashi Iwai 2021-08-04 @289 void *p = alloc_pages_exact(size, gfp);
37af81c5998f4b Takashi Iwai 2021-06-09 290
f84ba106a0185b Takashi Iwai 2021-08-04 291 if (p)
86072b28544f52 Takashi Iwai 2022-08-21 292 *addr = page_to_phys(virt_to_page(p));
f84ba106a0185b Takashi Iwai 2021-08-04 293 return p;
37af81c5998f4b Takashi Iwai 2021-06-09 294 }
37af81c5998f4b Takashi Iwai 2021-06-09 295
86072b28544f52 Takashi Iwai 2022-08-21 296 static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
86072b28544f52 Takashi Iwai 2022-08-21 297 {
86072b28544f52 Takashi Iwai 2022-08-21 298 return do_alloc_pages(size, &dmab->addr,
86072b28544f52 Takashi Iwai 2022-08-21 @299 snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
86072b28544f52 Takashi Iwai 2022-08-21 300 }
86072b28544f52 Takashi Iwai 2022-08-21 301
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again
2022-08-21 8:22 [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again Takashi Iwai
2022-08-21 11:48 ` kernel test robot
@ 2022-08-21 14:31 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2022-08-21 14:31 UTC (permalink / raw)
To: Takashi Iwai, alsa-devel; +Cc: kbuild-all
Hi Takashi,
I love your patch! Perhaps something to improve:
[auto build test WARNING on tiwai-sound/for-next]
[also build test WARNING on linus/master v6.0-rc1 next-20220819]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Takashi-Iwai/ALSA-memalloc-Revive-x86-specific-WC-page-allocations-again/20220821-162443
base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next
config: i386-randconfig-s001 (https://download.01.org/0day-ci/archive/20220821/202208212226.7Ji4ZW8k-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-5) 11.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/86072b28544f52618e4ce8336ba80be1d67f38d9
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Takashi-Iwai/ALSA-memalloc-Revive-x86-specific-WC-page-allocations-again/20220821-162443
git checkout 86072b28544f52618e4ce8336ba80be1d67f38d9
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash sound/core/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> sound/core/memalloc.c:705:41: sparse: sparse: incorrect type in initializer (different base types) @@ expected unsigned long gfp @@ got restricted gfp_t @@
sound/core/memalloc.c:705:41: sparse: expected unsigned long gfp
sound/core/memalloc.c:705:41: sparse: got restricted gfp_t
>> sound/core/memalloc.c:710:62: sparse: sparse: restricted gfp_t degrades to integer
>> sound/core/memalloc.c:711:29: sparse: sparse: invalid assignment: |=
>> sound/core/memalloc.c:711:29: sparse: left side has type unsigned long
>> sound/core/memalloc.c:711:29: sparse: right side has type restricted gfp_t
sound/core/memalloc.c:714:60: sparse: sparse: restricted gfp_t degrades to integer
sound/core/memalloc.c:715:38: sparse: sparse: restricted gfp_t degrades to integer
sound/core/memalloc.c:715:52: sparse: sparse: restricted gfp_t degrades to integer
sound/core/memalloc.c:289:43: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected restricted gfp_t [usertype] gfp_mask @@ got unsigned long gfp @@
sound/core/memalloc.c:289:43: sparse: expected restricted gfp_t [usertype] gfp_mask
sound/core/memalloc.c:289:43: sparse: got unsigned long gfp
sound/core/memalloc.c:299:52: sparse: sparse: incorrect type in argument 3 (different base types) @@ expected unsigned long gfp @@ got restricted gfp_t @@
sound/core/memalloc.c:299:52: sparse: expected unsigned long gfp
sound/core/memalloc.c:299:52: sparse: got restricted gfp_t
vim +705 sound/core/memalloc.c
699
700 /* manual page allocations with wc setup */
701 static void *do_alloc_fallback_pages(struct device *dev, size_t size,
702 dma_addr_t *addr, bool wc)
703 {
704 void *p;
> 705 unsigned long gfp = DEFAULT_GFP & ~__GFP_COMP;
706
707 again:
708 p = do_alloc_pages(size, addr, gfp);
709 if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
> 710 if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
> 711 gfp |= GFP_DMA32;
712 goto again;
713 }
714 if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
715 gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
716 goto again;
717 }
718 }
719 if (p && wc)
720 set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
721 return p;
722 }
723
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-08-21 14:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-21 8:22 [PATCH] ALSA: memalloc: Revive x86-specific WC page allocations again Takashi Iwai
2022-08-21 11:48 ` kernel test robot
2022-08-21 14:31 ` kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.