aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej S. Szmigiero <mail@maciej.szmigiero.name>2018-02-13 18:07:58 -0500
committerTakashi Iwai <tiwai@suse.de>2018-02-14 01:46:55 -0500
commit04f8773a3e980f60953e7aeb36ec6c2631e11f10 (patch)
treed6acfcbfd79924f50f46886683ca6c5f391d0b4f
parent055e0ae10f509482ca5b140e8e5f4a77e31efdd5 (diff)
ALSA: emu10k1: add a IOMMU workaround
The Audigy 2 CA0102 chip (but most likely others from the emu10k1 family, too) has a problem that from time to time it likes to do few DMA reads a bit beyond its normal allocation and gets very confused if these reads get blocked by a IOMMU. For the first (reserved) page this happens multiple times at every playback, for various synth pages it happens randomly, rarely for PCM playback buffers and the page table memory itself. All these reads seem to follow a similar pattern, observed read offsets beyond the allocation end were 0x00, 0x40, 0x80 and 0xc0 (PCI cache line multiples), so it looks like the device tries to accesses up to 256 extra bytes. As a workaround let's widen these DMA allocations by an extra page if we detect that the device is behind a non-passthrough IOMMU (the DMA memory should be relatively plenty on IOMMU systems). Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/emu10k1.h3
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c49
-rw-r--r--sound/pci/emu10k1/emupcm.c10
-rw-r--r--sound/pci/emu10k1/memory.c40
4 files changed, 93 insertions, 9 deletions
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index db32b7de52e0..5ebcc51c0a6a 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1710,6 +1710,7 @@ struct snd_emu10k1 {
1710 unsigned int ecard_ctrl; /* ecard control bits */ 1710 unsigned int ecard_ctrl; /* ecard control bits */
1711 unsigned int address_mode; /* address mode */ 1711 unsigned int address_mode; /* address mode */
1712 unsigned long dma_mask; /* PCI DMA mask */ 1712 unsigned long dma_mask; /* PCI DMA mask */
1713 bool iommu_workaround; /* IOMMU workaround needed */
1713 unsigned int delay_pcm_irq; /* in samples */ 1714 unsigned int delay_pcm_irq; /* in samples */
1714 int max_cache_pages; /* max memory size / PAGE_SIZE */ 1715 int max_cache_pages; /* max memory size / PAGE_SIZE */
1715 struct snd_dma_buffer silent_page; /* silent page */ 1716 struct snd_dma_buffer silent_page; /* silent page */
@@ -1877,6 +1878,8 @@ void snd_p16v_resume(struct snd_emu10k1 *emu);
1877/* memory allocation */ 1878/* memory allocation */
1878struct snd_util_memblk *snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream); 1879struct snd_util_memblk *snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream);
1879int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk); 1880int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
1881int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
1882 struct snd_dma_buffer *dmab);
1880struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size); 1883struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size);
1881int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk); 1884int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
1882int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size); 1885int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 8decd2a7a404..18267de3a269 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -36,6 +36,7 @@
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/interrupt.h> 38#include <linux/interrupt.h>
39#include <linux/iommu.h>
39#include <linux/pci.h> 40#include <linux/pci.h>
40#include <linux/slab.h> 41#include <linux/slab.h>
41#include <linux/vmalloc.h> 42#include <linux/vmalloc.h>
@@ -1758,6 +1759,38 @@ static struct snd_emu_chip_details emu_chip_details[] = {
1758 { } /* terminator */ 1759 { } /* terminator */
1759}; 1760};
1760 1761
1762/*
1763 * The chip (at least the Audigy 2 CA0102 chip, but most likely others, too)
1764 * has a problem that from time to time it likes to do few DMA reads a bit
1765 * beyond its normal allocation and gets very confused if these reads get
1766 * blocked by a IOMMU.
1767 *
1768 * This behaviour has been observed for the first (reserved) page
1769 * (for which it happens multiple times at every playback), often for various
1770 * synth pages and sometimes for PCM playback buffers and the page table
1771 * memory itself.
1772 *
1773 * As a workaround let's widen these DMA allocations by an extra page if we
1774 * detect that the device is behind a non-passthrough IOMMU.
1775 */
1776static void snd_emu10k1_detect_iommu(struct snd_emu10k1 *emu)
1777{
1778 struct iommu_domain *domain;
1779
1780 emu->iommu_workaround = false;
1781
1782 if (!iommu_present(emu->card->dev->bus))
1783 return;
1784
1785 domain = iommu_get_domain_for_dev(emu->card->dev);
1786 if (domain && domain->type == IOMMU_DOMAIN_IDENTITY)
1787 return;
1788
1789 dev_notice(emu->card->dev,
1790 "non-passthrough IOMMU detected, widening DMA allocations");
1791 emu->iommu_workaround = true;
1792}
1793
1761int snd_emu10k1_create(struct snd_card *card, 1794int snd_emu10k1_create(struct snd_card *card,
1762 struct pci_dev *pci, 1795 struct pci_dev *pci,
1763 unsigned short extin_mask, 1796 unsigned short extin_mask,
@@ -1770,6 +1803,7 @@ int snd_emu10k1_create(struct snd_card *card,
1770 struct snd_emu10k1 *emu; 1803 struct snd_emu10k1 *emu;
1771 int idx, err; 1804 int idx, err;
1772 int is_audigy; 1805 int is_audigy;
1806 size_t page_table_size;
1773 unsigned int silent_page; 1807 unsigned int silent_page;
1774 const struct snd_emu_chip_details *c; 1808 const struct snd_emu_chip_details *c;
1775 static struct snd_device_ops ops = { 1809 static struct snd_device_ops ops = {
@@ -1867,6 +1901,8 @@ int snd_emu10k1_create(struct snd_card *card,
1867 1901
1868 is_audigy = emu->audigy = c->emu10k2_chip; 1902 is_audigy = emu->audigy = c->emu10k2_chip;
1869 1903
1904 snd_emu10k1_detect_iommu(emu);
1905
1870 /* set addressing mode */ 1906 /* set addressing mode */
1871 emu->address_mode = is_audigy ? 0 : 1; 1907 emu->address_mode = is_audigy ? 0 : 1;
1872 /* set the DMA transfer mask */ 1908 /* set the DMA transfer mask */
@@ -1893,8 +1929,11 @@ int snd_emu10k1_create(struct snd_card *card,
1893 emu->port = pci_resource_start(pci, 0); 1929 emu->port = pci_resource_start(pci, 0);
1894 1930
1895 emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; 1931 emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
1896 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1932
1897 (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) { 1933 page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
1934 MAXPAGES0);
1935 if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
1936 &emu->ptb_pages) < 0) {
1898 err = -ENOMEM; 1937 err = -ENOMEM;
1899 goto error; 1938 goto error;
1900 } 1939 }
@@ -1910,8 +1949,8 @@ int snd_emu10k1_create(struct snd_card *card,
1910 goto error; 1949 goto error;
1911 } 1950 }
1912 1951
1913 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1952 if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
1914 EMUPAGESIZE, &emu->silent_page) < 0) { 1953 &emu->silent_page) < 0) {
1915 err = -ENOMEM; 1954 err = -ENOMEM;
1916 goto error; 1955 goto error;
1917 } 1956 }
@@ -1995,7 +2034,7 @@ int snd_emu10k1_create(struct snd_card *card,
1995 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; 2034 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
1996 2035
1997 /* Clear silent pages and set up pointers */ 2036 /* Clear silent pages and set up pointers */
1998 memset(emu->silent_page.area, 0, PAGE_SIZE); 2037 memset(emu->silent_page.area, 0, emu->silent_page.bytes);
1999 silent_page = emu->silent_page.addr << emu->address_mode; 2038 silent_page = emu->silent_page.addr << emu->address_mode;
2000 for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) 2039 for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
2001 ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); 2040 ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 2683b9717215..cefe613ef7b7 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -411,12 +411,20 @@ static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream,
411 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); 411 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
412 struct snd_pcm_runtime *runtime = substream->runtime; 412 struct snd_pcm_runtime *runtime = substream->runtime;
413 struct snd_emu10k1_pcm *epcm = runtime->private_data; 413 struct snd_emu10k1_pcm *epcm = runtime->private_data;
414 size_t alloc_size;
414 int err; 415 int err;
415 416
416 if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0) 417 if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
417 return err; 418 return err;
418 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) 419
420 alloc_size = params_buffer_bytes(hw_params);
421 if (emu->iommu_workaround)
422 alloc_size += EMUPAGESIZE;
423 err = snd_pcm_lib_malloc_pages(substream, alloc_size);
424 if (err < 0)
419 return err; 425 return err;
426 if (emu->iommu_workaround && runtime->dma_bytes >= EMUPAGESIZE)
427 runtime->dma_bytes -= EMUPAGESIZE;
420 if (err > 0) { /* change */ 428 if (err > 0) { /* change */
421 int mapped; 429 int mapped;
422 if (epcm->memblk != NULL) 430 if (epcm->memblk != NULL)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 1d0ce7356bbd..5865f3b90b34 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -377,6 +377,33 @@ int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk)
377 return snd_emu10k1_synth_free(emu, blk); 377 return snd_emu10k1_synth_free(emu, blk);
378} 378}
379 379
380/*
381 * allocate DMA pages, widening the allocation if necessary
382 *
383 * See the comment above snd_emu10k1_detect_iommu() in emu10k1_main.c why
384 * this might be needed.
385 *
386 * If you modify this function check whether __synth_free_pages() also needs
387 * changes.
388 */
389int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
390 struct snd_dma_buffer *dmab)
391{
392 if (emu->iommu_workaround) {
393 size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
394 size_t size_real = npages * PAGE_SIZE;
395
396 /*
397 * The device has been observed to accesses up to 256 extra
398 * bytes, but use 1k to be safe.
399 */
400 if (size_real < size + 1024)
401 size += PAGE_SIZE;
402 }
403
404 return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
405 snd_dma_pci_data(emu->pci), size, dmab);
406}
380 407
381/* 408/*
382 * memory allocation using multiple pages (for synth) 409 * memory allocation using multiple pages (for synth)
@@ -472,7 +499,15 @@ static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page,
472 continue; 499 continue;
473 dmab.area = emu->page_ptr_table[page]; 500 dmab.area = emu->page_ptr_table[page];
474 dmab.addr = emu->page_addr_table[page]; 501 dmab.addr = emu->page_addr_table[page];
502
503 /*
504 * please keep me in sync with logic in
505 * snd_emu10k1_alloc_pages_maybe_wider()
506 */
475 dmab.bytes = PAGE_SIZE; 507 dmab.bytes = PAGE_SIZE;
508 if (emu->iommu_workaround)
509 dmab.bytes *= 2;
510
476 snd_dma_free_pages(&dmab); 511 snd_dma_free_pages(&dmab);
477 emu->page_addr_table[page] = 0; 512 emu->page_addr_table[page] = 0;
478 emu->page_ptr_table[page] = NULL; 513 emu->page_ptr_table[page] = NULL;
@@ -491,9 +526,8 @@ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk
491 get_single_page_range(emu->memhdr, blk, &first_page, &last_page); 526 get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
492 /* allocate kernel pages */ 527 /* allocate kernel pages */
493 for (page = first_page; page <= last_page; page++) { 528 for (page = first_page; page <= last_page; page++) {
494 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 529 if (snd_emu10k1_alloc_pages_maybe_wider(emu, PAGE_SIZE,
495 snd_dma_pci_data(emu->pci), 530 &dmab) < 0)
496 PAGE_SIZE, &dmab) < 0)
497 goto __fail; 531 goto __fail;
498 if (!is_valid_page(emu, dmab.addr)) { 532 if (!is_valid_page(emu, dmab.addr)) {
499 snd_dma_free_pages(&dmab); 533 snd_dma_free_pages(&dmab);