summaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/memalloc.c44
-rw-r--r--sound/core/pcm_native.c24
-rw-r--r--sound/core/pcm_trace.h6
-rw-r--r--sound/core/rawmidi.c2
4 files changed, 46 insertions, 30 deletions
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index ba095558b6d1..7268304009ad 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -720,7 +720,6 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
struct snd_dma_sg_fallback {
size_t count;
struct page **pages;
- dma_addr_t *addrs;
};
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
@@ -732,38 +731,49 @@ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
kvfree(sgbuf->pages);
- kvfree(sgbuf->addrs);
kfree(sgbuf);
}
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
{
struct snd_dma_sg_fallback *sgbuf;
- struct page **pages;
- size_t i, count;
+ struct page **pagep, *curp;
+ size_t chunk, npages;
+ dma_addr_t addr;
void *p;
bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (!sgbuf)
return NULL;
- count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- pages = kvcalloc(count, sizeof(*pages), GFP_KERNEL);
- if (!pages)
- goto error;
- sgbuf->pages = pages;
- sgbuf->addrs = kvcalloc(count, sizeof(*sgbuf->addrs), GFP_KERNEL);
- if (!sgbuf->addrs)
+ size = PAGE_ALIGN(size);
+ sgbuf->count = size >> PAGE_SHIFT;
+ sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
+ if (!sgbuf->pages)
goto error;
- for (i = 0; i < count; sgbuf->count++, i++) {
- p = do_alloc_pages(dmab->dev.dev, PAGE_SIZE, &sgbuf->addrs[i], wc);
- if (!p)
- goto error;
- sgbuf->pages[i] = virt_to_page(p);
+ pagep = sgbuf->pages;
+ chunk = size;
+ while (size > 0) {
+ chunk = min(size, chunk);
+ p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc);
+ if (!p) {
+ if (chunk <= PAGE_SIZE)
+ goto error;
+ chunk >>= 1;
+ chunk = PAGE_SIZE << get_order(chunk);
+ continue;
+ }
+
+ size -= chunk;
+ /* fill pages */
+ npages = chunk >> PAGE_SHIFT;
+ curp = virt_to_page(p);
+ while (npages--)
+ *pagep++ = curp++;
}
- p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
+ p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL);
if (!p)
goto error;
dmab->private_data = sgbuf;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 33769ca78cc8..9c122e757efe 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -288,7 +288,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
&substream->runtime->hw_constraints;
struct snd_mask *m;
unsigned int k;
- struct snd_mask old_mask;
+ struct snd_mask old_mask __maybe_unused;
int changed;
for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
@@ -324,7 +324,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
&substream->runtime->hw_constraints;
struct snd_interval *i;
unsigned int k;
- struct snd_interval old_interval;
+ struct snd_interval old_interval __maybe_unused;
int changed;
for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
@@ -364,8 +364,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
unsigned int stamp;
struct snd_pcm_hw_rule *r;
unsigned int d;
- struct snd_mask old_mask;
- struct snd_interval old_interval;
+ struct snd_mask old_mask __maybe_unused;
+ struct snd_interval old_interval __maybe_unused;
bool again;
int changed, err = 0;
@@ -648,8 +648,8 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
-1
};
const int *v;
- struct snd_mask old_mask;
- struct snd_interval old_interval;
+ struct snd_mask old_mask __maybe_unused;
+ struct snd_interval old_interval __maybe_unused;
int changed;
for (v = vars; *v != -1; v++) {
@@ -1424,16 +1424,24 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
static int snd_pcm_do_start(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
+ int err;
+
if (substream->runtime->trigger_master != substream)
return 0;
- return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+ err = substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+ /* XRUN happened during the start */
+ if (err == -EPIPE)
+ __snd_pcm_set_state(substream->runtime, SNDRV_PCM_STATE_XRUN);
+ return err;
}
static void snd_pcm_undo_start(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
- if (substream->runtime->trigger_master == substream)
+ if (substream->runtime->trigger_master == substream) {
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+ substream->runtime->stop_operating = true;
+ }
}
static void snd_pcm_post_start(struct snd_pcm_substream *substream,
diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h
index f18da2050772..350b40b906ca 100644
--- a/sound/core/pcm_trace.h
+++ b/sound/core/pcm_trace.h
@@ -88,19 +88,19 @@ TRACE_EVENT(hw_ptr_error,
__field( unsigned int, device )
__field( unsigned int, number )
__field( unsigned int, stream )
- __field( const char *, reason )
+ __string( reason, why )
),
TP_fast_assign(
__entry->card = (substream)->pcm->card->number;
__entry->device = (substream)->pcm->device;
__entry->number = (substream)->number;
__entry->stream = (substream)->stream;
- __entry->reason = (why);
+ __assign_str(reason, why);
),
TP_printk("pcmC%dD%d%s/sub%d: ERROR: %s",
__entry->card, __entry->device,
__entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
- __entry->number, __entry->reason)
+ __entry->number, __get_str(reason))
);
TRACE_EVENT(applptr,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index d8edb6055072..7147fda66d93 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1050,7 +1050,6 @@ static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_runtime *runtime = substream->runtime;
struct snd_rawmidi_framing_tstamp *dest_ptr;
struct snd_rawmidi_framing_tstamp frame = { .tv_sec = tstamp->tv_sec, .tv_nsec = tstamp->tv_nsec };
- int dest_frames = 0;
int orig_count = src_count;
int frame_size = sizeof(struct snd_rawmidi_framing_tstamp);
@@ -1077,7 +1076,6 @@ static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream,
runtime->avail += frame_size;
runtime->hw_ptr += frame_size;
runtime->hw_ptr %= runtime->buffer_size;
- dest_frames++;
}
return orig_count - src_count;
}