aboutsummaryrefslogtreecommitdiff
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c130
1 files changed, 68 insertions, 62 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 09b4286c65f..b653ab001fb 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/pm_qos.h>
-#include <linux/uio.h>
+#include <linux/aio.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -190,12 +190,12 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
- printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+ pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
#endif
changed = snd_mask_refine(m, constrs_mask(constrs, k));
#ifdef RULES_DEBUG
- printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+ pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
#endif
if (changed)
params->cmask |= 1 << k;
@@ -210,21 +210,21 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
if (i->empty)
- printk("empty");
+ pr_cont("empty");
else
- printk("%c%u %u%c",
+ pr_cont("%c%u %u%c",
i->openmin ? '(' : '[', i->min,
i->max, i->openmax ? ')' : ']');
- printk(" -> ");
+ pr_cont(" -> ");
#endif
changed = snd_interval_refine(i, constrs_interval(constrs, k));
#ifdef RULES_DEBUG
if (i->empty)
- printk("empty\n");
+ pr_cont("empty\n");
else
- printk("%c%u %u%c\n",
+ pr_cont("%c%u %u%c\n",
i->openmin ? '(' : '[', i->min,
i->max, i->openmax ? ')' : ']');
#endif
@@ -255,18 +255,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
if (!doit)
continue;
#ifdef RULES_DEBUG
- printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
+ pr_debug("Rule %d [%p]: ", k, r->func);
if (r->var >= 0) {
- printk("%s = ", snd_pcm_hw_param_names[r->var]);
+ pr_cont("%s = ", snd_pcm_hw_param_names[r->var]);
if (hw_is_mask(r->var)) {
m = hw_param_mask(params, r->var);
- printk("%x", *m->bits);
+ pr_cont("%x", *m->bits);
} else {
i = hw_param_interval(params, r->var);
if (i->empty)
- printk("empty");
+ pr_cont("empty");
else
- printk("%c%u %u%c",
+ pr_cont("%c%u %u%c",
i->openmin ? '(' : '[', i->min,
i->max, i->openmax ? ')' : ']');
}
@@ -275,19 +275,19 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
changed = r->func(params, r);
#ifdef RULES_DEBUG
if (r->var >= 0) {
- printk(" -> ");
+ pr_cont(" -> ");
if (hw_is_mask(r->var))
- printk("%x", *m->bits);
+ pr_cont("%x", *m->bits);
else {
if (i->empty)
- printk("empty");
+ pr_cont("empty");
else
- printk("%c%u %u%c",
+ pr_cont("%c%u %u%c",
i->openmin ? '(' : '[', i->min,
i->max, i->openmax ? ')' : ']');
}
}
- printk("\n");
+ pr_cont("\n");
#endif
rstamps[k] = stamp;
if (changed && r->var >= 0) {
@@ -399,7 +399,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
return -EBADFD;
}
snd_pcm_stream_unlock_irq(substream);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
+#if IS_ENABLED(CONFIG_SND_PCM_OSS)
if (!substream->oss.oss)
#endif
if (atomic_read(&substream->mmap_count))
@@ -898,6 +898,8 @@ static struct action_ops snd_pcm_action_start = {
/**
* snd_pcm_start - start all linked streams
* @substream: the PCM substream instance
+ *
+ * Return: Zero if successful, or a negative error code.
*/
int snd_pcm_start(struct snd_pcm_substream *substream)
{
@@ -951,6 +953,8 @@ static struct action_ops snd_pcm_action_stop = {
* @state: PCM state after stopping the stream
*
* The state of each stream is then changed to the given state unconditionally.
+ *
+ * Return: Zero if successful, or a negative error code.
*/
int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
{
@@ -965,6 +969,8 @@ EXPORT_SYMBOL(snd_pcm_stop);
*
* After stopping, the state is changed to SETUP.
* Unlike snd_pcm_stop(), this affects only the given stream.
+ *
+ * Return: Zero if succesful, or a negative error code.
*/
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
{
@@ -1098,6 +1104,9 @@ static struct action_ops snd_pcm_action_suspend = {
* @substream: the PCM substream
*
* After this call, all streams are changed to SUSPENDED state.
+ *
+ * Return: Zero if successful (or @substream is %NULL), or a negative error
+ * code.
*/
int snd_pcm_suspend(struct snd_pcm_substream *substream)
{
@@ -1120,6 +1129,8 @@ EXPORT_SYMBOL(snd_pcm_suspend);
* @pcm: the PCM instance
*
* After this call, all streams are changed to SUSPENDED state.
+ *
+ * Return: Zero if successful (or @pcm is %NULL), or a negative error code.
*/
int snd_pcm_suspend_all(struct snd_pcm *pcm)
{
@@ -1343,6 +1354,8 @@ static struct action_ops snd_pcm_action_prepare = {
* snd_pcm_prepare - prepare the PCM substream to be triggerable
* @substream: the PCM substream instance
* @file: file to refer f_flags
+ *
+ * Return: Zero if successful, or a negative error code.
*/
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
struct file *file)
@@ -1528,7 +1541,8 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
result = -ESTRPIPE;
else {
- snd_printd("playback drain error (DMA or IRQ trouble?)\n");
+ dev_dbg(substream->pcm->card->dev,
+ "playback drain error (DMA or IRQ trouble?)\n");
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
result = -EIO;
}
@@ -1576,29 +1590,16 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
}
-/* WARNING: Don't forget to fput back the file */
-static struct file *snd_pcm_file_fd(int fd, int *fput_needed)
+static bool is_pcm_file(struct file *file)
{
- struct file *file;
- struct inode *inode;
+ struct inode *inode = file_inode(file);
unsigned int minor;
- file = fget_light(fd, fput_needed);
- if (!file)
- return NULL;
- inode = file->f_path.dentry->d_inode;
- if (!S_ISCHR(inode->i_mode) ||
- imajor(inode) != snd_major) {
- fput_light(file, *fput_needed);
- return NULL;
- }
+ if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
+ return false;
minor = iminor(inode);
- if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
- !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
- fput_light(file, *fput_needed);
- return NULL;
- }
- return file;
+ return snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) ||
+ snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
}
/*
@@ -1607,16 +1608,18 @@ static struct file *snd_pcm_file_fd(int fd, int *fput_needed)
static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
int res = 0;
- struct file *file;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
struct snd_pcm_group *group;
- int fput_needed;
+ struct fd f = fdget(fd);
- file = snd_pcm_file_fd(fd, &fput_needed);
- if (!file)
+ if (!f.file)
return -EBADFD;
- pcm_file = file->private_data;
+ if (!is_pcm_file(f.file)) {
+ res = -EBADFD;
+ goto _badf;
+ }
+ pcm_file = f.file->private_data;
substream1 = pcm_file->substream;
group = kmalloc(sizeof(*group), GFP_KERNEL);
if (!group) {
@@ -1636,6 +1639,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
}
if (!snd_pcm_stream_linked(substream)) {
substream->group = group;
+ group = NULL;
spin_lock_init(&substream->group->lock);
INIT_LIST_HEAD(&substream->group->substreams);
list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1649,9 +1653,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
up_write(&snd_pcm_link_rwsem);
_nolock:
snd_card_unref(substream1->pcm->card);
- fput_light(file, fput_needed);
- if (res < 0)
- kfree(group);
+ kfree(group);
+ _badf:
+ fdput(f);
return res;
}
@@ -2063,7 +2067,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
err = snd_pcm_hw_constraints_init(substream);
if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_init failed\n");
+ pcm_dbg(pcm, "snd_pcm_hw_constraints_init failed\n");
goto error;
}
@@ -2074,7 +2078,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
err = snd_pcm_hw_constraints_complete(substream);
if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_complete failed\n");
+ pcm_dbg(pcm, "snd_pcm_hw_constraints_complete failed\n");
goto error;
}
@@ -2425,6 +2429,7 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
+ /* Fall through */
case SNDRV_PCM_STATE_RUNNING:
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
@@ -2457,6 +2462,7 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
+ /* Fall through */
case SNDRV_PCM_STATE_RUNNING:
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
@@ -2604,7 +2610,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
return res;
}
}
- snd_printd("unknown ioctl = 0x%x\n", cmd);
+ pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
}
@@ -3196,6 +3202,14 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+#ifdef CONFIG_GENERIC_ALLOCATOR
+ if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+ return remap_pfn_range(area, area->vm_start,
+ substream->dma_buffer.addr >> PAGE_SHIFT,
+ area->vm_end - area->vm_start, area->vm_page_prot);
+ }
+#endif /* CONFIG_GENERIC_ALLOCATOR */
#ifdef ARCH_HAS_DMA_MMAP_COHERENT
if (!substream->ops->page &&
substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
@@ -3222,18 +3236,10 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
- long size;
- unsigned long offset;
+ struct snd_pcm_runtime *runtime = substream->runtime;;
area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
- area->vm_flags |= VM_IO;
- size = area->vm_end - area->vm_start;
- offset = area->vm_pgoff << PAGE_SHIFT;
- if (io_remap_pfn_range(area, area->vm_start,
- (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
- size, area->vm_page_prot))
- return -EAGAIN;
- return 0;
+ return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
}
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);