| .. | .. |
|---|
| 31 | 31 | module_param(max_alloc_per_card, ulong, 0644); |
|---|
| 32 | 32 | MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card."); |
|---|
| 33 | 33 | |
|---|
| 34 | +static void __update_allocated_size(struct snd_card *card, ssize_t bytes) |
|---|
| 35 | +{ |
|---|
| 36 | + card->total_pcm_alloc_bytes += bytes; |
|---|
| 37 | +} |
|---|
| 38 | + |
|---|
| 39 | +static void update_allocated_size(struct snd_card *card, ssize_t bytes) |
|---|
| 40 | +{ |
|---|
| 41 | + mutex_lock(&card->memory_mutex); |
|---|
| 42 | + __update_allocated_size(card, bytes); |
|---|
| 43 | + mutex_unlock(&card->memory_mutex); |
|---|
| 44 | +} |
|---|
| 45 | + |
|---|
| 46 | +static void decrease_allocated_size(struct snd_card *card, size_t bytes) |
|---|
| 47 | +{ |
|---|
| 48 | + mutex_lock(&card->memory_mutex); |
|---|
| 49 | + WARN_ON(card->total_pcm_alloc_bytes < bytes); |
|---|
| 50 | + __update_allocated_size(card, -(ssize_t)bytes); |
|---|
| 51 | + mutex_unlock(&card->memory_mutex); |
|---|
| 52 | +} |
|---|
| 53 | + |
|---|
| 34 | 54 | static int do_alloc_pages(struct snd_card *card, int type, struct device *dev, |
|---|
| 35 | 55 | size_t size, struct snd_dma_buffer *dmab) |
|---|
| 36 | 56 | { |
|---|
| 37 | 57 | int err; |
|---|
| 38 | 58 | |
|---|
| 59 | + /* check and reserve the requested size */ |
|---|
| 60 | + mutex_lock(&card->memory_mutex); |
|---|
| 39 | 61 | if (max_alloc_per_card && |
|---|
| 40 | | - card->total_pcm_alloc_bytes + size > max_alloc_per_card) |
|---|
| 62 | + card->total_pcm_alloc_bytes + size > max_alloc_per_card) { |
|---|
| 63 | + mutex_unlock(&card->memory_mutex); |
|---|
| 41 | 64 | return -ENOMEM; |
|---|
| 65 | + } |
|---|
| 66 | + __update_allocated_size(card, size); |
|---|
| 67 | + mutex_unlock(&card->memory_mutex); |
|---|
| 42 | 68 | |
|---|
| 43 | 69 | err = snd_dma_alloc_pages(type, dev, size, dmab); |
|---|
| 44 | 70 | if (!err) { |
|---|
| 45 | | - mutex_lock(&card->memory_mutex); |
|---|
| 46 | | - card->total_pcm_alloc_bytes += dmab->bytes; |
|---|
| 47 | | - mutex_unlock(&card->memory_mutex); |
|---|
| 71 | + /* the actual allocation size might be bigger than requested, |
|---|
| 72 | + * and we need to correct the account |
|---|
| 73 | + */ |
|---|
| 74 | + if (dmab->bytes != size) |
|---|
| 75 | + update_allocated_size(card, dmab->bytes - size); |
|---|
| 76 | + } else { |
|---|
| 77 | + /* take back on allocation failure */ |
|---|
| 78 | + decrease_allocated_size(card, size); |
|---|
| 48 | 79 | } |
|---|
| 49 | 80 | return err; |
|---|
| 50 | 81 | } |
|---|
| .. | .. |
|---|
| 53 | 84 | { |
|---|
| 54 | 85 | if (!dmab->area) |
|---|
| 55 | 86 | return; |
|---|
| 56 | | - mutex_lock(&card->memory_mutex); |
|---|
| 57 | | - WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes); |
|---|
| 58 | | - card->total_pcm_alloc_bytes -= dmab->bytes; |
|---|
| 59 | | - mutex_unlock(&card->memory_mutex); |
|---|
| 87 | + decrease_allocated_size(card, dmab->bytes); |
|---|
| 60 | 88 | snd_dma_free_pages(dmab); |
|---|
| 61 | 89 | dmab->area = NULL; |
|---|
| 62 | 90 | } |
|---|