[ALSA] alsa: nopage
Convert ALSA from nopage to fault. Switch from OOM to SIGBUS if the resource is not available. Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Родитель
bba8dee782
Коммит
3ad5afcd5f
|
@ -3033,26 +3033,23 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
|
|||
/*
|
||||
* mmap status record
|
||||
*/
|
||||
static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct page * page;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
page = virt_to_page(runtime->status);
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = virt_to_page(runtime->status);
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_status =
|
||||
{
|
||||
.nopage = snd_pcm_mmap_status_nopage,
|
||||
.fault = snd_pcm_mmap_status_fault,
|
||||
};
|
||||
|
||||
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
|
||||
|
@ -3076,26 +3073,23 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
|
|||
/*
|
||||
* mmap control record
|
||||
*/
|
||||
static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct page * page;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
page = virt_to_page(runtime->control);
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = virt_to_page(runtime->control);
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_control =
|
||||
{
|
||||
.nopage = snd_pcm_mmap_control_nopage,
|
||||
.fault = snd_pcm_mmap_control_fault,
|
||||
};
|
||||
|
||||
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
|
||||
|
@ -3132,10 +3126,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
|
|||
#endif /* coherent mmap */
|
||||
|
||||
/*
|
||||
* nopage callback for mmapping a RAM page
|
||||
* fault callback for mmapping a RAM page
|
||||
*/
|
||||
static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
@ -3145,33 +3139,30 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
|
|||
size_t dma_bytes;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
offset = area->vm_pgoff << PAGE_SHIFT;
|
||||
offset += address - area->vm_start;
|
||||
snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS);
|
||||
offset = vmf->pgoff << PAGE_SHIFT;
|
||||
dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
|
||||
if (offset > dma_bytes - PAGE_SIZE)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
if (substream->ops->page) {
|
||||
page = substream->ops->page(substream, offset);
|
||||
if (! page)
|
||||
return NOPAGE_OOM; /* XXX: is this really due to OOM? */
|
||||
if (!page)
|
||||
return VM_FAULT_SIGBUS;
|
||||
} else {
|
||||
vaddr = runtime->dma_area + offset;
|
||||
page = virt_to_page(vaddr);
|
||||
}
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_data =
|
||||
{
|
||||
.open = snd_pcm_mmap_data_open,
|
||||
.close = snd_pcm_mmap_data_close,
|
||||
.nopage = snd_pcm_mmap_data_nopage,
|
||||
.fault = snd_pcm_mmap_data_fault,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче