ALSA: ctxfi - fix PTP address initialization

After hours of debugging, I finally found the reason why some source
and runtime combination does not work. The PTP (page table pages)
address must be aligned. I am not sure how much, but alignment to
PAGE_SIZE is sufficient. Also, use ALSA's page allocation routines
to ensure proper virtual -> physical address translation.

Cc: <stable@kernel.org>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>

+25 -36
+2 -13
sound/pci/ctxfi/ctatc.c
··· 166 167 static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index) 168 { 169 - struct ct_vm *vm; 170 - void *kvirt_addr; 171 - unsigned long phys_addr; 172 - 173 - vm = atc->vm; 174 - kvirt_addr = vm->get_ptp_virt(vm, index); 175 - if (kvirt_addr == NULL) 176 - phys_addr = (~0UL); 177 - else 178 - phys_addr = virt_to_phys(kvirt_addr); 179 - 180 - return phys_addr; 181 } 182 183 static unsigned int convert_format(snd_pcm_format_t snd_format) ··· 1658 } 1659 1660 /* Set up device virtual memory management object */ 1661 - err = ct_vm_create(&atc->vm); 1662 if (err < 0) 1663 goto error1; 1664
··· 166 167 static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index) 168 { 169 + return atc->vm->get_ptp_phys(atc->vm, index); 170 } 171 172 static unsigned int convert_format(snd_pcm_format_t snd_format) ··· 1669 } 1670 1671 /* Set up device virtual memory management object */ 1672 + err = ct_vm_create(&atc->vm, pci); 1673 if (err < 0) 1674 goto error1; 1675
+18 -20
sound/pci/ctxfi/ctvmem.c
··· 138 return NULL; 139 } 140 141 - ptp = vm->ptp[0]; 142 pte_start = (block->addr >> CT_PAGE_SHIFT); 143 pages = block->size >> CT_PAGE_SHIFT; 144 for (i = 0; i < pages; i++) { ··· 158 } 159 160 /* * 161 - * return the host (kmalloced) addr of the @index-th device 162 - * page talbe page on success, or NULL on failure. 163 - * The first returned NULL indicates the termination. 164 * */ 165 - static void * 166 - ct_get_ptp_virt(struct ct_vm *vm, int index) 167 { 168 - void *addr; 169 170 - addr = (index >= CT_PTP_NUM) ? NULL : vm->ptp[index]; 171 172 return addr; 173 } 174 175 - int ct_vm_create(struct ct_vm **rvm) 176 { 177 struct ct_vm *vm; 178 struct ct_vm_block *block; 179 - int i; 180 181 *rvm = NULL; 182 ··· 188 189 /* Allocate page table pages */ 190 for (i = 0; i < CT_PTP_NUM; i++) { 191 - vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL); 192 - if (!vm->ptp[i]) 193 break; 194 } 195 - if (!i) { 196 /* no page table pages are allocated */ 197 - kfree(vm); 198 return -ENOMEM; 199 } 200 vm->size = CT_ADDRS_PER_PAGE * i; 201 - /* Initialise remaining ptps */ 202 - for (; i < CT_PTP_NUM; i++) 203 - vm->ptp[i] = NULL; 204 - 205 vm->map = ct_vm_map; 206 vm->unmap = ct_vm_unmap; 207 - vm->get_ptp_virt = ct_get_ptp_virt; 208 INIT_LIST_HEAD(&vm->unused); 209 INIT_LIST_HEAD(&vm->used); 210 block = kzalloc(sizeof(*block), GFP_KERNEL); ··· 240 241 /* free allocated page table pages */ 242 for (i = 0; i < CT_PTP_NUM; i++) 243 - kfree(vm->ptp[i]); 244 245 vm->size = 0; 246
··· 138 return NULL; 139 } 140 141 + ptp = (unsigned long *)vm->ptp[0].area; 142 pte_start = (block->addr >> CT_PAGE_SHIFT); 143 pages = block->size >> CT_PAGE_SHIFT; 144 for (i = 0; i < pages; i++) { ··· 158 } 159 160 /* * 161 + * return the host physical addr of the @index-th device 162 + * page table page on success, or ~0UL on failure. 163 + * The first returned ~0UL indicates the termination. 164 * */ 165 + static dma_addr_t 166 + ct_get_ptp_phys(struct ct_vm *vm, int index) 167 { 168 + dma_addr_t addr; 169 170 + addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; 171 172 return addr; 173 } 174 175 + int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci) 176 { 177 struct ct_vm *vm; 178 struct ct_vm_block *block; 179 + int i, err = 0; 180 181 *rvm = NULL; 182 ··· 188 189 /* Allocate page table pages */ 190 for (i = 0; i < CT_PTP_NUM; i++) { 191 + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 192 + snd_dma_pci_data(pci), 193 + PAGE_SIZE, &vm->ptp[i]); 194 + if (err < 0) 195 break; 196 } 197 + if (err < 0) { 198 /* no page table pages are allocated */ 199 + ct_vm_destroy(vm); 200 return -ENOMEM; 201 } 202 vm->size = CT_ADDRS_PER_PAGE * i; 203 vm->map = ct_vm_map; 204 vm->unmap = ct_vm_unmap; 205 + vm->get_ptp_phys = ct_get_ptp_phys; 206 INIT_LIST_HEAD(&vm->unused); 207 INIT_LIST_HEAD(&vm->used); 208 block = kzalloc(sizeof(*block), GFP_KERNEL); ··· 242 243 /* free allocated page table pages */ 244 for (i = 0; i < CT_PTP_NUM; i++) 245 + snd_dma_free_pages(&vm->ptp[i]); 246 247 vm->size = 0; 248
+5 -3
sound/pci/ctxfi/ctvmem.h
··· 22 23 #include <linux/mutex.h> 24 #include <linux/list.h> 25 26 /* The chip can handle the page table of 4k pages 27 * (emu20k1 can handle even 8k pages, but we don't use it right now) ··· 43 44 /* Virtual memory management object for card device */ 45 struct ct_vm { 46 - void *ptp[CT_PTP_NUM]; /* Device page table pages */ 47 unsigned int size; /* Available addr space in bytes */ 48 struct list_head unused; /* List of unused blocks */ 49 struct list_head used; /* List of used blocks */ ··· 54 int size); 55 /* Unmap device logical addr area. */ 56 void (*unmap)(struct ct_vm *, struct ct_vm_block *block); 57 - void *(*get_ptp_virt)(struct ct_vm *vm, int index); 58 }; 59 60 - int ct_vm_create(struct ct_vm **rvm); 61 void ct_vm_destroy(struct ct_vm *vm); 62 63 #endif /* CTVMEM_H */
··· 22 23 #include <linux/mutex.h> 24 #include <linux/list.h> 25 + #include <linux/pci.h> 26 + #include <sound/memalloc.h> 27 28 /* The chip can handle the page table of 4k pages 29 * (emu20k1 can handle even 8k pages, but we don't use it right now) ··· 41 42 /* Virtual memory management object for card device */ 43 struct ct_vm { 44 + struct snd_dma_buffer ptp[CT_PTP_NUM]; /* Device page table pages */ 45 unsigned int size; /* Available addr space in bytes */ 46 struct list_head unused; /* List of unused blocks */ 47 struct list_head used; /* List of used blocks */ ··· 52 int size); 53 /* Unmap device logical addr area. */ 54 void (*unmap)(struct ct_vm *, struct ct_vm_block *block); 55 + dma_addr_t (*get_ptp_phys)(struct ct_vm *vm, int index); 56 }; 57 58 + int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci); 59 void ct_vm_destroy(struct ct_vm *vm); 60 61 #endif /* CTVMEM_H */