From 3b5b899ca67db07a4c4825911072221f99e157e2 Mon Sep 17 00:00:00 2001 From: Abhijeet Kumar Date: Tue, 23 Jan 2018 23:00:52 +0530 Subject: ALSA: hda: Make use of core codec functions to sync power state Since sync_power_state is moved to core it's better to use the helper function to ensure the actual power state reaches target instead of using the local helper functions already exsisting in hda code. Signed-off-by: Abhijeet Kumar Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 28 +--------------------------- sound/pci/hda/hda_local.h | 6 +++++- 2 files changed, 6 insertions(+), 28 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e018ecbf78a8..5bc3a7468e17 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2702,32 +2702,6 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, } EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all); -/* - * wait until the state is reached, returns the current state - */ -static unsigned int hda_sync_power_state(struct hda_codec *codec, - hda_nid_t fg, - unsigned int power_state) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(500); - unsigned int state, actual_state; - - for (;;) { - state = snd_hda_codec_read(codec, fg, 0, - AC_VERB_GET_POWER_STATE, 0); - if (state & AC_PWRST_ERROR) - break; - actual_state = (state >> 4) & 0x0f; - if (actual_state == power_state) - break; - if (time_after_eq(jiffies, end_time)) - break; - /* wait until the codec reachs to the target state */ - msleep(1); - } - return state; -} - /** * snd_hda_codec_eapd_power_filter - A power filter callback for EAPD * @codec: the HDA codec @@ -2790,7 +2764,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, state); snd_hda_codec_set_power_to_all(codec, fg, power_state); } - state = hda_sync_power_state(codec, fg, power_state); + state = snd_hda_sync_power_state(codec, fg, power_state); if (!(state & AC_PWRST_ERROR)) break; } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 5b5c324c99b9..321e78baa63c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -622,7 +622,11 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid, { return snd_hdac_check_power_state(&codec->core, nid, target_state); } - +static inline bool snd_hda_sync_power_state(struct hda_codec *codec, + hda_nid_t nid, unsigned int target_state) +{ + return snd_hdac_sync_power_state(&codec->core, nid, target_state); +} unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec, hda_nid_t nid, unsigned int power_state); -- cgit v1.2.3 From a4463c92db0805581f4dfb700f72533cf25ebd48 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 14 Feb 2018 00:04:58 +0100 Subject: ALSA: emu10k1: remove reserved_page The emu10k1-family chips need the first page (index 0) reserved in their page tables for some reason (every emu10k1 driver I've checked does this without much of an explanation). Using the first page for normal samples results in a broken playback. However, we already have a dummy page allocated - so called "silent page" and, in fact, had always been setting it as the first page in the chip page table because an initialization of every entry of the page table to point to a silent page happens after and overwrites the reserved_page allocation. So the only thing remaining to remove the reserved_page allocation is a trivial change to the page allocation logic to ignore the first page entry and start its allocations from the second entry (index 1). Signed-off-by: Maciej S. Szmigiero Signed-off-by: Takashi Iwai --- include/sound/emu10k1.h | 1 - sound/pci/emu10k1/emu10k1_main.c | 11 ----------- sound/pci/emu10k1/memory.c | 8 ++++++-- 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'sound/pci') diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 4f42affe777c..db32b7de52e0 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1718,7 +1718,6 @@ struct snd_emu10k1 { struct snd_dma_buffer p16v_buffer; struct snd_util_memhdr *memhdr; /* page allocation list */ - struct snd_emu10k1_memblk *reserved_page; /* reserved page */ struct list_head mapped_link_head; struct list_head mapped_order_link_head; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index ccf4415a1c7b..a0a4d31ded53 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1272,12 +1272,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) release_firmware(emu->dock_fw); if (emu->irq >= 0) free_irq(emu->irq, emu); - /* remove reserved page */ - if (emu->reserved_page) { - snd_emu10k1_synth_free(emu, - (struct snd_util_memblk *)emu->reserved_page); - emu->reserved_page = NULL; - } snd_util_memhdr_free(emu->memhdr); if (emu->silent_page.area) snd_dma_free_pages(&emu->silent_page); @@ -1993,11 +1987,6 @@ int snd_emu10k1_create(struct snd_card *card, SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; - emu->reserved_page = (struct snd_emu10k1_memblk *) - snd_emu10k1_synth_alloc(emu, 4096); - if (emu->reserved_page) - emu->reserved_page->map_locked = 1; - /* Clear silent pages and set up pointers */ memset(emu->silent_page.area, 0, PAGE_SIZE); silent_page = emu->silent_page.addr << emu->address_mode; diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4f1f69be1865..eaa61024ac7f 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -102,7 +102,7 @@ static void emu10k1_memblk_init(struct snd_emu10k1_memblk *blk) */ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct list_head **nextp) { - int page = 0, found_page = -ENOMEM; + int page = 1, found_page = -ENOMEM; int max_size = npages; int size; struct list_head *candidate = &emu->mapped_link_head; @@ -147,6 +147,10 @@ static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) page = search_empty_map_area(emu, blk->pages, &next); if (page < 0) /* not found */ return page; + if (page == 0) { + dev_err(emu->card->dev, "trying to map zero (reserved) page\n"); + return -EINVAL; + } /* insert this block in the proper position of mapped list */ list_add_tail(&blk->mapped_link, next); /* append this as a newest block in order list */ @@ -177,7 +181,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) q = get_emu10k1_memblk(p, mapped_link); start_page = q->mapped_page + q->pages; } else - start_page = 0; + start_page = 1; if ((p = blk->mapped_link.next) != &emu->mapped_link_head) { q = get_emu10k1_memblk(p, mapped_link); end_page = q->mapped_page; -- cgit v1.2.3 From 70d0bc7dca918a0add6da817bae70f334fb4cc60 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 14 Feb 2018 00:05:16 +0100 Subject: ALSA: emu10k1: use dma_set_mask_and_coherent() We have been calling dma_set_mask() and then dma_set_coherent_mask() with the same value, but there is a dma_set_mask_and_coherent() function that does exactly that so let's use it instead. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index a0a4d31ded53..11e868f569d6 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1871,8 +1871,7 @@ int snd_emu10k1_create(struct snd_card *card, emu->address_mode = is_audigy ? 0 : 1; /* set the DMA transfer mask */ emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; - if (dma_set_mask(&pci->dev, emu->dma_mask) < 0 || - dma_set_coherent_mask(&pci->dev, emu->dma_mask) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, emu->dma_mask) < 0) { dev_err(card->dev, "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); -- cgit v1.2.3 From 541b9bad169d2422c7c7e3905b105930a1b6eb32 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 14 Feb 2018 00:06:18 +0100 Subject: ALSA: emu10k1: add optional debug printouts with DMA addresses When we get a IOMMU page fault for a emu10k1 device it is very hard to discover which of chip many DMA allocations triggered it (since on a IOMMU system the DMA address space is often very different from the CPU one). Let's add optional debug printouts providing this information. These debug printouts are only enabled on an explicit request via the kernel dynamic debug mechanism. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 8 ++++++++ sound/pci/emu10k1/memory.c | 15 +++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 11e868f569d6..8decd2a7a404 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1898,6 +1898,9 @@ int snd_emu10k1_create(struct snd_card *card, err = -ENOMEM; goto error; } + dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n", + (unsigned long)emu->ptb_pages.addr, + (unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes)); emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); emu->page_addr_table = vmalloc(emu->max_cache_pages * @@ -1912,6 +1915,11 @@ int snd_emu10k1_create(struct snd_card *card, err = -ENOMEM; goto error; } + dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n", + (unsigned long)emu->silent_page.addr, + (unsigned long)(emu->silent_page.addr + + emu->silent_page.bytes)); + emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE); if (emu->memhdr == NULL) { err = -ENOMEM; diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index eaa61024ac7f..fcb04cbbc9ab 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -34,7 +34,10 @@ * aligned pages in others */ #define __set_ptb_entry(emu,page,addr) \ - (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page))) + (((__le32 *)(emu)->ptb_pages.area)[page] = \ + cpu_to_le32(((addr) << (emu->address_mode)) | (page))) +#define __get_ptb_entry(emu, page) \ + (le32_to_cpu(((__le32 *)(emu)->ptb_pages.area)[page])) #define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) #define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) @@ -44,8 +47,7 @@ /* get offset address from aligned page */ #define aligned_page_offset(page) ((page) << PAGE_SHIFT) -#if PAGE_SIZE == 4096 -/* page size == EMUPAGESIZE */ +#if PAGE_SIZE == EMUPAGESIZE && !IS_ENABLED(CONFIG_DYNAMIC_DEBUG) /* fill PTB entrie(s) corresponding to page with addr */ #define set_ptb_entry(emu,page,addr) __set_ptb_entry(emu,page,addr) /* fill PTB entrie(s) corresponding to page with silence pointer */ @@ -58,6 +60,8 @@ static inline void set_ptb_entry(struct snd_emu10k1 *emu, int page, dma_addr_t a page *= UNIT_PAGES; for (i = 0; i < UNIT_PAGES; i++, page++) { __set_ptb_entry(emu, page, addr); + dev_dbg(emu->card->dev, "mapped page %d to entry %.8x\n", page, + (unsigned int)__get_ptb_entry(emu, page)); addr += EMUPAGESIZE; } } @@ -65,9 +69,12 @@ static inline void set_silent_ptb(struct snd_emu10k1 *emu, int page) { int i; page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) + for (i = 0; i < UNIT_PAGES; i++, page++) { /* do not increment ptr */ __set_ptb_entry(emu, page, emu->silent_page.addr); + dev_dbg(emu->card->dev, "mapped silent page %d to entry %.8x\n", + page, (unsigned int)__get_ptb_entry(emu, page)); + } } #endif /* PAGE_SIZE */ -- cgit v1.2.3 From 055e0ae10f509482ca5b140e8e5f4a77e31efdd5 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 14 Feb 2018 00:06:34 +0100 Subject: ALSA: emu10k1: make sure synth DMA pages are allocated with DMA functions Commit a5003fc04113 ("[ALSA] emu10k1 - simplify page allocation for synth") switched from using the DMA allocator for synth DMA pages to manually calling alloc_page(). However, this usage has an implicit assumption that the DMA address space for the emu10k1-family chip is the same as the CPU physical address space which is not true for a system with a IOMMU. Since this made the synth part of the driver non-functional on such systems let's effectively revert that commit (while keeping the __synth_free_pages() simplification). Signed-off-by: Maciej S. Szmigiero Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/memory.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index fcb04cbbc9ab..1d0ce7356bbd 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -461,10 +461,19 @@ static void get_single_page_range(struct snd_util_memhdr *hdr, static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, int last_page) { + struct snd_dma_buffer dmab; int page; + dmab.dev.type = SNDRV_DMA_TYPE_DEV; + dmab.dev.dev = snd_dma_pci_data(emu->pci); + for (page = first_page; page <= last_page; page++) { - free_page((unsigned long)emu->page_ptr_table[page]); + if (emu->page_ptr_table[page] == NULL) + continue; + dmab.area = emu->page_ptr_table[page]; + dmab.addr = emu->page_addr_table[page]; + dmab.bytes = PAGE_SIZE; + snd_dma_free_pages(&dmab); emu->page_addr_table[page] = 0; emu->page_ptr_table[page] = NULL; } @@ -476,30 +485,31 @@ static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) { int page, first_page, last_page; + struct snd_dma_buffer dmab; emu10k1_memblk_init(blk); get_single_page_range(emu->memhdr, blk, &first_page, &last_page); /* allocate kernel pages */ for (page = first_page; page <= last_page; page++) { - /* first try to allocate from <4GB zone */ - struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | - __GFP_NOWARN); - if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) { - if (p) - __free_page(p); - /* try to allocate from <16MB zone */ - p = alloc_page(GFP_ATOMIC | GFP_DMA | - __GFP_NORETRY | /* no OOM-killer */ - __GFP_NOWARN); - } - if (!p) { - __synth_free_pages(emu, first_page, page - 1); - return -ENOMEM; + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(emu->pci), + PAGE_SIZE, &dmab) < 0) + goto __fail; + if (!is_valid_page(emu, dmab.addr)) { + snd_dma_free_pages(&dmab); + goto __fail; } - emu->page_addr_table[page] = page_to_phys(p); - emu->page_ptr_table[page] = page_address(p); + emu->page_addr_table[page] = dmab.addr; + emu->page_ptr_table[page] = dmab.area; } return 0; + +__fail: + /* release allocated pages */ + last_page = page - 1; + __synth_free_pages(emu, first_page, last_page); + + return -ENOMEM; } /* -- cgit v1.2.3 From 04f8773a3e980f60953e7aeb36ec6c2631e11f10 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 14 Feb 2018 00:07:58 +0100 Subject: 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 Signed-off-by: Takashi Iwai --- include/sound/emu10k1.h | 3 +++ sound/pci/emu10k1/emu10k1_main.c | 49 ++++++++++++++++++++++++++++++++++++---- sound/pci/emu10k1/emupcm.c | 10 +++++++- sound/pci/emu10k1/memory.c | 40 +++++++++++++++++++++++++++++--- 4 files changed, 93 insertions(+), 9 deletions(-) (limited to 'sound/pci') 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 { unsigned int ecard_ctrl; /* ecard control bits */ unsigned int address_mode; /* address mode */ unsigned long dma_mask; /* PCI DMA mask */ + bool iommu_workaround; /* IOMMU workaround needed */ unsigned int delay_pcm_irq; /* in samples */ int max_cache_pages; /* max memory size / PAGE_SIZE */ struct snd_dma_buffer silent_page; /* silent page */ @@ -1877,6 +1878,8 @@ void snd_p16v_resume(struct snd_emu10k1 *emu); /* memory allocation */ struct snd_util_memblk *snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream); int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk); +int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size, + struct snd_dma_buffer *dmab); struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size); int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk); int 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 @@ #include #include #include +#include #include #include #include @@ -1758,6 +1759,38 @@ static struct snd_emu_chip_details emu_chip_details[] = { { } /* terminator */ }; +/* + * The chip (at least the Audigy 2 CA0102 chip, but most likely others, 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. + * + * This behaviour has been observed for the first (reserved) page + * (for which it happens multiple times at every playback), often for various + * synth pages and sometimes for PCM playback buffers and the page table + * memory itself. + * + * 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. + */ +static void snd_emu10k1_detect_iommu(struct snd_emu10k1 *emu) +{ + struct iommu_domain *domain; + + emu->iommu_workaround = false; + + if (!iommu_present(emu->card->dev->bus)) + return; + + domain = iommu_get_domain_for_dev(emu->card->dev); + if (domain && domain->type == IOMMU_DOMAIN_IDENTITY) + return; + + dev_notice(emu->card->dev, + "non-passthrough IOMMU detected, widening DMA allocations"); + emu->iommu_workaround = true; +} + int snd_emu10k1_create(struct snd_card *card, struct pci_dev *pci, unsigned short extin_mask, @@ -1770,6 +1803,7 @@ int snd_emu10k1_create(struct snd_card *card, struct snd_emu10k1 *emu; int idx, err; int is_audigy; + size_t page_table_size; unsigned int silent_page; const struct snd_emu_chip_details *c; static struct snd_device_ops ops = { @@ -1867,6 +1901,8 @@ int snd_emu10k1_create(struct snd_card *card, is_audigy = emu->audigy = c->emu10k2_chip; + snd_emu10k1_detect_iommu(emu); + /* set addressing mode */ emu->address_mode = is_audigy ? 0 : 1; /* set the DMA transfer mask */ @@ -1893,8 +1929,11 @@ int snd_emu10k1_create(struct snd_card *card, emu->port = pci_resource_start(pci, 0); emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) { + + page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 : + MAXPAGES0); + if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size, + &emu->ptb_pages) < 0) { err = -ENOMEM; goto error; } @@ -1910,8 +1949,8 @@ int snd_emu10k1_create(struct snd_card *card, goto error; } - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - EMUPAGESIZE, &emu->silent_page) < 0) { + if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE, + &emu->silent_page) < 0) { err = -ENOMEM; goto error; } @@ -1995,7 +2034,7 @@ int snd_emu10k1_create(struct snd_card *card, 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; /* Clear silent pages and set up pointers */ - memset(emu->silent_page.area, 0, PAGE_SIZE); + memset(emu->silent_page.area, 0, emu->silent_page.bytes); silent_page = emu->silent_page.addr << emu->address_mode; for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) ((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, struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_emu10k1_pcm *epcm = runtime->private_data; + size_t alloc_size; int err; if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0) return err; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) + + alloc_size = params_buffer_bytes(hw_params); + if (emu->iommu_workaround) + alloc_size += EMUPAGESIZE; + err = snd_pcm_lib_malloc_pages(substream, alloc_size); + if (err < 0) return err; + if (emu->iommu_workaround && runtime->dma_bytes >= EMUPAGESIZE) + runtime->dma_bytes -= EMUPAGESIZE; if (err > 0) { /* change */ int mapped; 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) return snd_emu10k1_synth_free(emu, blk); } +/* + * allocate DMA pages, widening the allocation if necessary + * + * See the comment above snd_emu10k1_detect_iommu() in emu10k1_main.c why + * this might be needed. + * + * If you modify this function check whether __synth_free_pages() also needs + * changes. + */ +int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size, + struct snd_dma_buffer *dmab) +{ + if (emu->iommu_workaround) { + size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + size_t size_real = npages * PAGE_SIZE; + + /* + * The device has been observed to accesses up to 256 extra + * bytes, but use 1k to be safe. + */ + if (size_real < size + 1024) + size += PAGE_SIZE; + } + + return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(emu->pci), size, dmab); +} /* * memory allocation using multiple pages (for synth) @@ -472,7 +499,15 @@ static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, continue; dmab.area = emu->page_ptr_table[page]; dmab.addr = emu->page_addr_table[page]; + + /* + * please keep me in sync with logic in + * snd_emu10k1_alloc_pages_maybe_wider() + */ dmab.bytes = PAGE_SIZE; + if (emu->iommu_workaround) + dmab.bytes *= 2; + snd_dma_free_pages(&dmab); emu->page_addr_table[page] = 0; emu->page_ptr_table[page] = NULL; @@ -491,9 +526,8 @@ static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk get_single_page_range(emu->memhdr, blk, &first_page, &last_page); /* allocate kernel pages */ for (page = first_page; page <= last_page; page++) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - PAGE_SIZE, &dmab) < 0) + if (snd_emu10k1_alloc_pages_maybe_wider(emu, PAGE_SIZE, + &dmab) < 0) goto __fail; if (!is_valid_page(emu, dmab.addr)) { snd_dma_free_pages(&dmab); -- cgit v1.2.3 From 248a380a3c2e7e3363f26c17b6923b430cf6463e Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 16 Feb 2018 21:53:15 -0800 Subject: ALSA: hda-beep: add SPDX identifiers Add SPDX GPLv2.0+ identifiers and update authors email Signed-off-by: Matt Ranostay Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 17 ++--------------- sound/pci/hda/hda_beep.h | 17 ++--------------- 2 files changed, 4 insertions(+), 30 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index c397e7da0eac..066b5b59c4d7 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Digital Beep Input Interface for HD-audio codec * - * Author: Matt Ranostay + * Author: Matt Ranostay * Copyright (c) 2008 Embedded Alley Solutions Inc - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This driver is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 1052ad380e97..d1a6a9c1329a 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -1,22 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Digital Beep Input Interface for HD-audio codec * - * Author: Matt Ranostay + * Author: Matt Ranostay * Copyright (c) 2008 Embedded Alley Solutions Inc - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This driver is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __SOUND_HDA_BEEP_H -- cgit v1.2.3 From 338e17d3f58e9868a12af7deb1edcfb40bd588b2 Mon Sep 17 00:00:00 2001 From: Joey Pabalinas Date: Thu, 1 Mar 2018 04:17:07 -1000 Subject: ALSA: ice1712: replace strcpy() with strlcpy() Replace unsafe usages of strcpy() to copy the name argument into the sid.name buffer with strlcpy() to guard against possible buffer overflows. Signed-off-by: Joey Pabalinas Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Takashi Iwai --- sound/pci/ice1712/juli.c | 8 ++++---- sound/pci/ice1712/quartet.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 0dbaccf61f33..21806bab4757 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -425,10 +426,9 @@ DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1); static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) { - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - /* FIXME: strcpy is bad. */ - strcpy(sid.name, name); + struct snd_ctl_elem_id sid = {0}; + + strlcpy(sid.name, name, sizeof(sid.name)); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_find_id(card, &sid); } diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index d145b5eb7ff8..5bc836241c97 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -785,10 +786,9 @@ DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) { - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - /* FIXME: strcpy is bad. */ - strcpy(sid.name, name); + struct snd_ctl_elem_id sid = {0}; + + strlcpy(sid.name, name, sizeof(sid.name)); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_find_id(card, &sid); } -- cgit v1.2.3 From 0bc66fd3b688ae33ac073de7e79ba1223ecc465c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 12 Mar 2018 15:01:00 +0000 Subject: ALSA: echoaudio: remove redundant initialization of pointer 'pipe' The pointer 'pipe' is being initialized with a value that is never read and it is re-assigned later, hence the initialization is redundant and can be removed. Also remove pointer 'runtime' as it is no longer required. Cleans up clang warning: sound/pci/echoaudio/echoaudio.c:740:20: warning: Value stored to 'pipe' during its initialization is never read Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index d68f99e076a8..0935a5c8741f 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -736,8 +736,7 @@ static int pcm_prepare(struct snd_pcm_substream *substream) static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct echoaudio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audiopipe *pipe = runtime->private_data; + struct audiopipe *pipe; int i, err; u32 channelmask = 0; struct snd_pcm_substream *s; -- cgit v1.2.3 From 491f833134ac474434e1c950925c58b2ac13ca72 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Tue, 13 Mar 2018 16:40:08 +0530 Subject: ALSA: hda: Add Icelake PCI ID Icelake is a next generation Intel platform. Add PCI ID for it. Signed-off-by: Guneshwor Singh Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/pci') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 96143df19b21..32acab080781 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2426,6 +2426,9 @@ static const struct pci_device_id azx_ids[] = { /* Cannonlake */ { PCI_DEVICE(0x8086, 0x9dc8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Icelake */ + { PCI_DEVICE(0x8086, 0x34c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, -- cgit v1.2.3