Merge tag 'sched-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / sound / drivers / opl4 / opl4_proc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Functions for the OPL4 proc file
4  * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5  */
6
7 #include "opl4_local.h"
8 #include <linux/vmalloc.h>
9 #include <linux/export.h>
10 #include <sound/info.h>
11
12 static int snd_opl4_mem_proc_open(struct snd_info_entry *entry,
13                                   unsigned short mode, void **file_private_data)
14 {
15         struct snd_opl4 *opl4 = entry->private_data;
16
17         mutex_lock(&opl4->access_mutex);
18         if (opl4->memory_access) {
19                 mutex_unlock(&opl4->access_mutex);
20                 return -EBUSY;
21         }
22         opl4->memory_access++;
23         mutex_unlock(&opl4->access_mutex);
24         return 0;
25 }
26
27 static int snd_opl4_mem_proc_release(struct snd_info_entry *entry,
28                                      unsigned short mode, void *file_private_data)
29 {
30         struct snd_opl4 *opl4 = entry->private_data;
31
32         mutex_lock(&opl4->access_mutex);
33         opl4->memory_access--;
34         mutex_unlock(&opl4->access_mutex);
35         return 0;
36 }
37
38 static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry,
39                                       void *file_private_data,
40                                       struct file *file, char __user *_buf,
41                                       size_t count, loff_t pos)
42 {
43         struct snd_opl4 *opl4 = entry->private_data;
44         char* buf;
45
46         buf = vmalloc(count);
47         if (!buf)
48                 return -ENOMEM;
49         snd_opl4_read_memory(opl4, buf, pos, count);
50         if (copy_to_user(_buf, buf, count)) {
51                 vfree(buf);
52                 return -EFAULT;
53         }
54         vfree(buf);
55         return count;
56 }
57
58 static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,
59                                        void *file_private_data,
60                                        struct file *file,
61                                        const char __user *_buf,
62                                        size_t count, loff_t pos)
63 {
64         struct snd_opl4 *opl4 = entry->private_data;
65         char *buf;
66
67         buf = vmalloc(count);
68         if (!buf)
69                 return -ENOMEM;
70         if (copy_from_user(buf, _buf, count)) {
71                 vfree(buf);
72                 return -EFAULT;
73         }
74         snd_opl4_write_memory(opl4, buf, pos, count);
75         vfree(buf);
76         return count;
77 }
78
79 static const struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
80         .open = snd_opl4_mem_proc_open,
81         .release = snd_opl4_mem_proc_release,
82         .read = snd_opl4_mem_proc_read,
83         .write = snd_opl4_mem_proc_write,
84 };
85
86 int snd_opl4_create_proc(struct snd_opl4 *opl4)
87 {
88         struct snd_info_entry *entry;
89
90         entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root);
91         if (entry) {
92                 if (opl4->hardware < OPL3_HW_OPL4_ML) {
93                         /* OPL4 can access 4 MB external ROM/SRAM */
94                         entry->mode |= 0200;
95                         entry->size = 4 * 1024 * 1024;
96                 } else {
97                         /* OPL4-ML has 1 MB internal ROM */
98                         entry->size = 1 * 1024 * 1024;
99                 }
100                 entry->content = SNDRV_INFO_CONTENT_DATA;
101                 entry->c.ops = &snd_opl4_mem_proc_ops;
102                 entry->module = THIS_MODULE;
103                 entry->private_data = opl4;
104         }
105         opl4->proc_entry = entry;
106         return 0;
107 }
108
109 void snd_opl4_free_proc(struct snd_opl4 *opl4)
110 {
111         snd_info_free_entry(opl4->proc_entry);
112 }