On Tue, 07 Aug 2018 11:00:39 +0200, Hans Hu(SH-RD) wrote:
Then the next step would be to fake sg-buffer from this straight buffer. Revert the above, and modify sgbuf.c to the following:
- Allocate a large continuous buffer
- Assign each page in this large buffer
If this still works, it's not about vmap, but it just means that the physically ordered pages do matter -- implicitly showing that the snooping behavior isn't properly turned on / off on the controller.
To fake SG-buffer, I did this test: restore all the codes to the original, then added some codes in snd_malloc_sgbuf_pages() like below, the result is badly niose.
Not really what I meant. Rather something like below (totally untested).
Takashi
---
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 84fffabdd129..643f6cb2048c 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -68,7 +68,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, size_t *res_size) { struct snd_sg_buf *sgbuf; - unsigned int i, pages, chunk, maxpages; + unsigned int i, pages; struct snd_dma_buffer tmpb; struct snd_sg_page *table; struct page **pgtable; @@ -90,38 +90,18 @@ void *snd_malloc_sgbuf_pages(struct device *device, goto _failed; sgbuf->page_table = pgtable;
- /* allocate pages */ - maxpages = MAX_ALLOC_PAGES; - while (pages > 0) { - chunk = pages; - /* don't be too eager to take a huge chunk */ - if (chunk > maxpages) - chunk = maxpages; - chunk <<= PAGE_SHIFT; - if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, - chunk, &tmpb) < 0) { - if (!sgbuf->pages) - goto _failed; - if (!res_size) - goto _failed; - size = sgbuf->pages * PAGE_SIZE; - break; - } - chunk = tmpb.bytes >> PAGE_SHIFT; - for (i = 0; i < chunk; i++) { - table->buf = tmpb.area; - table->addr = tmpb.addr; - if (!i) - table->addr |= chunk; /* mark head */ - table++; - *pgtable++ = virt_to_page(tmpb.area); - tmpb.area += PAGE_SIZE; - tmpb.addr += PAGE_SIZE; - } - sgbuf->pages += chunk; - pages -= chunk; - if (chunk < maxpages) - maxpages = chunk; + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, device, size, &tmpb) < 0) + goto _failed; + + for (i = 0; i < pages; i++) { + table->buf = tmpb.area; + table->addr = tmpb.addr; + if (!i) + table->addr |= pages; /* mark head */ + table++; + *pgtable++ = virt_to_page(tmpb.area); + tmpb.area += PAGE_SIZE; + tmpb.addr += PAGE_SIZE; }
sgbuf->size = size;