at v3.8 14 kB view raw
1/* 2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 3 * Takashi Iwai <tiwai@suse.de> 4 * 5 * Generic memory allocators 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include <linux/module.h> 25#include <linux/proc_fs.h> 26#include <linux/init.h> 27#include <linux/pci.h> 28#include <linux/slab.h> 29#include <linux/mm.h> 30#include <linux/seq_file.h> 31#include <asm/uaccess.h> 32#include <linux/dma-mapping.h> 33#include <linux/moduleparam.h> 34#include <linux/mutex.h> 35#include <sound/memalloc.h> 36 37 38MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); 39MODULE_DESCRIPTION("Memory allocator for ALSA system."); 40MODULE_LICENSE("GPL"); 41 42 43/* 44 */ 45 46static DEFINE_MUTEX(list_mutex); 47static LIST_HEAD(mem_list_head); 48 49/* buffer preservation list */ 50struct snd_mem_list { 51 struct snd_dma_buffer buffer; 52 unsigned int id; 53 struct list_head list; 54}; 55 56/* id for pre-allocated buffers */ 57#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1 58 59/* 60 * 61 * Generic memory allocators 62 * 63 */ 64 65static long snd_allocated_pages; /* holding the number of allocated pages */ 66 67static inline void inc_snd_pages(int order) 68{ 69 snd_allocated_pages += 1 << order; 70} 71 72static inline void dec_snd_pages(int order) 73{ 74 snd_allocated_pages -= 1 << order; 75} 76 77/** 78 * snd_malloc_pages - allocate pages with the given size 79 * @size: the size to allocate in bytes 80 * @gfp_flags: the allocation conditions, GFP_XXX 81 * 82 * Allocates the physically contiguous pages with the given size. 83 * 84 * Returns the pointer of the buffer, or NULL if no enoguh memory. 85 */ 86void *snd_malloc_pages(size_t size, gfp_t gfp_flags) 87{ 88 int pg; 89 void *res; 90 91 if (WARN_ON(!size)) 92 return NULL; 93 if (WARN_ON(!gfp_flags)) 94 return NULL; 95 gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ 96 pg = get_order(size); 97 if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) 98 inc_snd_pages(pg); 99 return res; 100} 101 102/** 103 * snd_free_pages - release the pages 104 * @ptr: the buffer pointer to release 105 * @size: the allocated buffer size 106 * 107 * Releases the buffer allocated via snd_malloc_pages(). 108 */ 109void snd_free_pages(void *ptr, size_t size) 110{ 111 int pg; 112 113 if (ptr == NULL) 114 return; 115 pg = get_order(size); 116 dec_snd_pages(pg); 117 free_pages((unsigned long) ptr, pg); 118} 119 120/* 121 * 122 * Bus-specific memory allocators 123 * 124 */ 125 126#ifdef CONFIG_HAS_DMA 127/* allocate the coherent DMA pages */ 128static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) 129{ 130 int pg; 131 void *res; 132 gfp_t gfp_flags; 133 134 if (WARN_ON(!dma)) 135 return NULL; 136 pg = get_order(size); 137 gfp_flags = GFP_KERNEL 138 | __GFP_COMP /* compound page lets parts be mapped */ 139 | __GFP_NORETRY /* don't trigger OOM-killer */ 140 | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ 141 res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags); 142 if (res != NULL) 143 inc_snd_pages(pg); 144 145 return res; 146} 147 148/* free the coherent DMA pages */ 149static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, 150 dma_addr_t dma) 151{ 152 int pg; 153 154 if (ptr == NULL) 155 return; 156 pg = get_order(size); 157 dec_snd_pages(pg); 158 dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); 159} 160#endif /* CONFIG_HAS_DMA */ 161 162/* 163 * 164 * ALSA generic memory management 165 * 166 */ 167 168 169/** 170 * snd_dma_alloc_pages - allocate the buffer area according to the given type 171 * @type: the DMA buffer type 172 * @device: the device pointer 173 * @size: the buffer size to allocate 174 * @dmab: buffer allocation record to store the allocated data 175 * 176 * Calls the memory-allocator function for the corresponding 177 * buffer type. 178 * 179 * Returns zero if the buffer with the given size is allocated successfully, 180 * other a negative value at error. 181 */ 182int snd_dma_alloc_pages(int type, struct device *device, size_t size, 183 struct snd_dma_buffer *dmab) 184{ 185 if (WARN_ON(!size)) 186 return -ENXIO; 187 if (WARN_ON(!dmab)) 188 return -ENXIO; 189 190 dmab->dev.type = type; 191 dmab->dev.dev = device; 192 dmab->bytes = 0; 193 switch (type) { 194 case SNDRV_DMA_TYPE_CONTINUOUS: 195 dmab->area = snd_malloc_pages(size, 196 (__force gfp_t)(unsigned long)device); 197 dmab->addr = 0; 198 break; 199#ifdef CONFIG_HAS_DMA 200 case SNDRV_DMA_TYPE_DEV: 201 dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); 202 break; 203#endif 204#ifdef CONFIG_SND_DMA_SGBUF 205 case SNDRV_DMA_TYPE_DEV_SG: 206 snd_malloc_sgbuf_pages(device, size, dmab, NULL); 207 break; 208#endif 209 default: 210 printk(KERN_ERR "snd-malloc: invalid device type %d\n", type); 211 dmab->area = NULL; 212 dmab->addr = 0; 213 return -ENXIO; 214 } 215 if (! dmab->area) 216 return -ENOMEM; 217 dmab->bytes = size; 218 return 0; 219} 220 221/** 222 * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback 223 * @type: the DMA buffer type 224 * @device: the device pointer 225 * @size: the buffer size to allocate 226 * @dmab: buffer allocation record to store the allocated data 227 * 228 * Calls the memory-allocator function for the corresponding 229 * buffer type. When no space is left, this function reduces the size and 230 * tries to allocate again. The size actually allocated is stored in 231 * res_size argument. 232 * 233 * Returns zero if the buffer with the given size is allocated successfully, 234 * other a negative value at error. 235 */ 236int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, 237 struct snd_dma_buffer *dmab) 238{ 239 int err; 240 241 while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { 242 size_t aligned_size; 243 if (err != -ENOMEM) 244 return err; 245 if (size <= PAGE_SIZE) 246 return -ENOMEM; 247 aligned_size = PAGE_SIZE << get_order(size); 248 if (size != aligned_size) 249 size = aligned_size; 250 else 251 size >>= 1; 252 } 253 if (! dmab->area) 254 return -ENOMEM; 255 return 0; 256} 257 258 259/** 260 * snd_dma_free_pages - release the allocated buffer 261 * @dmab: the buffer allocation record to release 262 * 263 * Releases the allocated buffer via snd_dma_alloc_pages(). 264 */ 265void snd_dma_free_pages(struct snd_dma_buffer *dmab) 266{ 267 switch (dmab->dev.type) { 268 case SNDRV_DMA_TYPE_CONTINUOUS: 269 snd_free_pages(dmab->area, dmab->bytes); 270 break; 271#ifdef CONFIG_HAS_DMA 272 case SNDRV_DMA_TYPE_DEV: 273 snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); 274 break; 275#endif 276#ifdef CONFIG_SND_DMA_SGBUF 277 case SNDRV_DMA_TYPE_DEV_SG: 278 snd_free_sgbuf_pages(dmab); 279 break; 280#endif 281 default: 282 printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type); 283 } 284} 285 286 287/** 288 * snd_dma_get_reserved - get the reserved buffer for the given device 289 * @dmab: the buffer allocation record to store 290 * @id: the buffer id 291 * 292 * Looks for the reserved-buffer list and re-uses if the same buffer 293 * is found in the list. When the buffer is found, it's removed from the free list. 294 * 295 * Returns the size of buffer if the buffer is found, or zero if not found. 296 */ 297size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) 298{ 299 struct snd_mem_list *mem; 300 301 if (WARN_ON(!dmab)) 302 return 0; 303 304 mutex_lock(&list_mutex); 305 list_for_each_entry(mem, &mem_list_head, list) { 306 if (mem->id == id && 307 (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL || 308 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) { 309 struct device *dev = dmab->dev.dev; 310 list_del(&mem->list); 311 *dmab = mem->buffer; 312 if (dmab->dev.dev == NULL) 313 dmab->dev.dev = dev; 314 kfree(mem); 315 mutex_unlock(&list_mutex); 316 return dmab->bytes; 317 } 318 } 319 mutex_unlock(&list_mutex); 320 return 0; 321} 322 323/** 324 * snd_dma_reserve_buf - reserve the buffer 325 * @dmab: the buffer to reserve 326 * @id: the buffer id 327 * 328 * Reserves the given buffer as a reserved buffer. 329 * 330 * Returns zero if successful, or a negative code at error. 331 */ 332int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id) 333{ 334 struct snd_mem_list *mem; 335 336 if (WARN_ON(!dmab)) 337 return -EINVAL; 338 mem = kmalloc(sizeof(*mem), GFP_KERNEL); 339 if (! mem) 340 return -ENOMEM; 341 mutex_lock(&list_mutex); 342 mem->buffer = *dmab; 343 mem->id = id; 344 list_add_tail(&mem->list, &mem_list_head); 345 mutex_unlock(&list_mutex); 346 return 0; 347} 348 349/* 350 * purge all reserved buffers 351 */ 352static void free_all_reserved_pages(void) 353{ 354 struct list_head *p; 355 struct snd_mem_list *mem; 356 357 mutex_lock(&list_mutex); 358 while (! list_empty(&mem_list_head)) { 359 p = mem_list_head.next; 360 mem = list_entry(p, struct snd_mem_list, list); 361 list_del(p); 362 snd_dma_free_pages(&mem->buffer); 363 kfree(mem); 364 } 365 mutex_unlock(&list_mutex); 366} 367 368 369#ifdef CONFIG_PROC_FS 370/* 371 * proc file interface 372 */ 373#define SND_MEM_PROC_FILE "driver/snd-page-alloc" 374static struct proc_dir_entry *snd_mem_proc; 375 376static int snd_mem_proc_read(struct seq_file *seq, void *offset) 377{ 378 long pages = snd_allocated_pages >> (PAGE_SHIFT-12); 379 struct snd_mem_list *mem; 380 int devno; 381 static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" }; 382 383 mutex_lock(&list_mutex); 384 seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", 385 pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); 386 devno = 0; 387 list_for_each_entry(mem, &mem_list_head, list) { 388 devno++; 389 seq_printf(seq, "buffer %d : ID %08x : type %s\n", 390 devno, mem->id, types[mem->buffer.dev.type]); 391 seq_printf(seq, " addr = 0x%lx, size = %d bytes\n", 392 (unsigned long)mem->buffer.addr, 393 (int)mem->buffer.bytes); 394 } 395 mutex_unlock(&list_mutex); 396 return 0; 397} 398 399static int snd_mem_proc_open(struct inode *inode, struct file *file) 400{ 401 return single_open(file, snd_mem_proc_read, NULL); 402} 403 404/* FIXME: for pci only - other bus? */ 405#ifdef CONFIG_PCI 406#define gettoken(bufp) strsep(bufp, " \t\n") 407 408static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, 409 size_t count, loff_t * ppos) 410{ 411 char buf[128]; 412 char *token, *p; 413 414 if (count > sizeof(buf) - 1) 415 return -EINVAL; 416 if (copy_from_user(buf, buffer, count)) 417 return -EFAULT; 418 buf[count] = '\0'; 419 420 p = buf; 421 token = gettoken(&p); 422 if (! token || *token == '#') 423 return count; 424 if (strcmp(token, "add") == 0) { 425 char *endp; 426 int vendor, device, size, buffers; 427 long mask; 428 int i, alloced; 429 struct pci_dev *pci; 430 431 if ((token = gettoken(&p)) == NULL || 432 (vendor = simple_strtol(token, NULL, 0)) <= 0 || 433 (token = gettoken(&p)) == NULL || 434 (device = simple_strtol(token, NULL, 0)) <= 0 || 435 (token = gettoken(&p)) == NULL || 436 (mask = simple_strtol(token, NULL, 0)) < 0 || 437 (token = gettoken(&p)) == NULL || 438 (size = memparse(token, &endp)) < 64*1024 || 439 size > 16*1024*1024 /* too big */ || 440 (token = gettoken(&p)) == NULL || 441 (buffers = simple_strtol(token, NULL, 0)) <= 0 || 442 buffers > 4) { 443 printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); 444 return count; 445 } 446 vendor &= 0xffff; 447 device &= 0xffff; 448 449 alloced = 0; 450 pci = NULL; 451 while ((pci = pci_get_device(vendor, device, pci)) != NULL) { 452 if (mask > 0 && mask < 0xffffffff) { 453 if (pci_set_dma_mask(pci, mask) < 0 || 454 pci_set_consistent_dma_mask(pci, mask) < 0) { 455 printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); 456 pci_dev_put(pci); 457 return count; 458 } 459 } 460 for (i = 0; i < buffers; i++) { 461 struct snd_dma_buffer dmab; 462 memset(&dmab, 0, sizeof(dmab)); 463 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 464 size, &dmab) < 0) { 465 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); 466 pci_dev_put(pci); 467 return count; 468 } 469 snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); 470 } 471 alloced++; 472 } 473 if (! alloced) { 474 for (i = 0; i < buffers; i++) { 475 struct snd_dma_buffer dmab; 476 memset(&dmab, 0, sizeof(dmab)); 477 /* FIXME: We can allocate only in ZONE_DMA 478 * without a device pointer! 479 */ 480 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL, 481 size, &dmab) < 0) { 482 printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); 483 break; 484 } 485 snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device)); 486 } 487 } 488 } else if (strcmp(token, "erase") == 0) 489 /* FIXME: need for releasing each buffer chunk? */ 490 free_all_reserved_pages(); 491 else 492 printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); 493 return count; 494} 495#endif /* CONFIG_PCI */ 496 497static const struct file_operations snd_mem_proc_fops = { 498 .owner = THIS_MODULE, 499 .open = snd_mem_proc_open, 500 .read = seq_read, 501#ifdef CONFIG_PCI 502 .write = snd_mem_proc_write, 503#endif 504 .llseek = seq_lseek, 505 .release = single_release, 506}; 507 508#endif /* CONFIG_PROC_FS */ 509 510/* 511 * module entry 512 */ 513 514static int __init snd_mem_init(void) 515{ 516#ifdef CONFIG_PROC_FS 517 snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL, 518 &snd_mem_proc_fops); 519#endif 520 return 0; 521} 522 523static void __exit snd_mem_exit(void) 524{ 525 remove_proc_entry(SND_MEM_PROC_FILE, NULL); 526 free_all_reserved_pages(); 527 if (snd_allocated_pages > 0) 528 printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); 529} 530 531 532module_init(snd_mem_init) 533module_exit(snd_mem_exit) 534 535 536/* 537 * exports 538 */ 539EXPORT_SYMBOL(snd_dma_alloc_pages); 540EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); 541EXPORT_SYMBOL(snd_dma_free_pages); 542 543EXPORT_SYMBOL(snd_dma_get_reserved_buf); 544EXPORT_SYMBOL(snd_dma_reserve_buf); 545 546EXPORT_SYMBOL(snd_malloc_pages); 547EXPORT_SYMBOL(snd_free_pages);