Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: info - Implement common llseek for binary mode

The llseek implementation is identical for existing driver implementations,
so let's merge to the common layer. The same code for the text proc file
can be used even for the binary proc file.

The driver can provide its own llseek method if needed. Then the common
code will be skipped.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+32 -129
+32 -28
sound/core/info.c
··· 164 164 { 165 165 struct snd_info_private_data *data; 166 166 struct snd_info_entry *entry; 167 - loff_t ret; 167 + loff_t ret = -EINVAL, size; 168 168 169 169 data = file->private_data; 170 170 entry = data->entry; 171 171 mutex_lock(&entry->access); 172 - switch (entry->content) { 173 - case SNDRV_INFO_CONTENT_TEXT: 174 - switch (orig) { 175 - case SEEK_SET: 176 - file->f_pos = offset; 177 - ret = file->f_pos; 178 - goto out; 179 - case SEEK_CUR: 180 - file->f_pos += offset; 181 - ret = file->f_pos; 182 - goto out; 183 - case SEEK_END: 184 - default: 185 - ret = -EINVAL; 186 - goto out; 187 - } 188 - break; 189 - case SNDRV_INFO_CONTENT_DATA: 190 - if (entry->c.ops->llseek) { 191 - ret = entry->c.ops->llseek(entry, 192 - data->file_private_data, 193 - file, offset, orig); 194 - goto out; 195 - } 196 - break; 172 + if (entry->content == SNDRV_INFO_CONTENT_DATA && 173 + entry->c.ops->llseek) { 174 + offset = entry->c.ops->llseek(entry, 175 + data->file_private_data, 176 + file, offset, orig); 177 + goto out; 197 178 } 198 - ret = -ENXIO; 199 - out: 179 + if (entry->content == SNDRV_INFO_CONTENT_DATA) 180 + size = entry->size; 181 + else 182 + size = 0; 183 + switch (orig) { 184 + case SEEK_SET: 185 + break; 186 + case SEEK_CUR: 187 + offset += file->f_pos; 188 + break; 189 + case SEEK_END: 190 + if (!size) 191 + goto out; 192 + offset += size; 193 + break; 194 + default: 195 + goto out; 196 + } 197 + if (offset < 0) 198 + goto out; 199 + if (size && offset > size) 200 + offset = size; 201 + file->f_pos = offset; 202 + ret = offset; 203 + out: 200 204 mutex_unlock(&entry->access); 201 205 return ret; 202 206 }
-24
sound/drivers/opl4/opl4_proc.c
··· 90 90 return count; 91 91 } 92 92 93 - static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, 94 - void *file_private_data, 95 - struct file *file, 96 - loff_t offset, int orig) 97 - { 98 - switch (orig) { 99 - case SEEK_SET: 100 - file->f_pos = offset; 101 - break; 102 - case SEEK_CUR: 103 - file->f_pos += offset; 104 - break; 105 - case SEEK_END: /* offset is negative */ 106 - file->f_pos = entry->size + offset; 107 - break; 108 - default: 109 - return -EINVAL; 110 - } 111 - if (file->f_pos > entry->size) 112 - file->f_pos = entry->size; 113 - return file->f_pos; 114 - } 115 - 116 93 static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { 117 94 .open = snd_opl4_mem_proc_open, 118 95 .release = snd_opl4_mem_proc_release, 119 96 .read = snd_opl4_mem_proc_read, 120 97 .write = snd_opl4_mem_proc_write, 121 - .llseek = snd_opl4_mem_proc_llseek, 122 98 }; 123 99 124 100 int snd_opl4_create_proc(struct snd_opl4 *opl4)
-26
sound/isa/gus/gus_mem_proc.c
··· 46 46 return count; 47 47 } 48 48 49 - static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, 50 - void *private_file_data, 51 - struct file *file, 52 - loff_t offset, int orig) 53 - { 54 - struct gus_proc_private *priv = entry->private_data; 55 - 56 - switch (orig) { 57 - case SEEK_SET: 58 - file->f_pos = offset; 59 - break; 60 - case SEEK_CUR: 61 - file->f_pos += offset; 62 - break; 63 - case SEEK_END: /* offset is negative */ 64 - file->f_pos = priv->size + offset; 65 - break; 66 - default: 67 - return -EINVAL; 68 - } 69 - if (file->f_pos > priv->size) 70 - file->f_pos = priv->size; 71 - return file->f_pos; 72 - } 73 - 74 49 static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) 75 50 { 76 51 struct gus_proc_private *priv = entry->private_data; ··· 54 79 55 80 static struct snd_info_entry_ops snd_gf1_mem_proc_ops = { 56 81 .read = snd_gf1_mem_proc_dump, 57 - .llseek = snd_gf1_mem_proc_llseek, 58 82 }; 59 83 60 84 int snd_gf1_mem_proc_init(struct snd_gus_card * gus)
-51
sound/pci/mixart/mixart.c
··· 1102 1102 /* 1103 1103 * proc interface 1104 1104 */ 1105 - static loff_t snd_mixart_BA0_llseek(struct snd_info_entry *entry, 1106 - void *private_file_data, 1107 - struct file *file, 1108 - loff_t offset, int orig) 1109 - { 1110 - offset = offset & ~3; /* 4 bytes aligned */ 1111 - 1112 - switch(orig) { 1113 - case SEEK_SET: 1114 - file->f_pos = offset; 1115 - break; 1116 - case SEEK_CUR: 1117 - file->f_pos += offset; 1118 - break; 1119 - case SEEK_END: /* offset is negative */ 1120 - file->f_pos = MIXART_BA0_SIZE + offset; 1121 - break; 1122 - default: 1123 - return -EINVAL; 1124 - } 1125 - if(file->f_pos > MIXART_BA0_SIZE) 1126 - file->f_pos = MIXART_BA0_SIZE; 1127 - return file->f_pos; 1128 - } 1129 - 1130 - static loff_t snd_mixart_BA1_llseek(struct snd_info_entry *entry, 1131 - void *private_file_data, 1132 - struct file *file, 1133 - loff_t offset, int orig) 1134 - { 1135 - offset = offset & ~3; /* 4 bytes aligned */ 1136 - 1137 - switch(orig) { 1138 - case SEEK_SET: 1139 - file->f_pos = offset; 1140 - break; 1141 - case SEEK_CUR: 1142 - file->f_pos += offset; 1143 - break; 1144 - case SEEK_END: /* offset is negative */ 1145 - file->f_pos = MIXART_BA1_SIZE + offset; 1146 - break; 1147 - default: 1148 - return -EINVAL; 1149 - } 1150 - if(file->f_pos > MIXART_BA1_SIZE) 1151 - file->f_pos = MIXART_BA1_SIZE; 1152 - return file->f_pos; 1153 - } 1154 1105 1155 1106 /* 1156 1107 mixart_BA0 proc interface for BAR 0 - read callback ··· 1137 1186 1138 1187 static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { 1139 1188 .read = snd_mixart_BA0_read, 1140 - .llseek = snd_mixart_BA0_llseek 1141 1189 }; 1142 1190 1143 1191 static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { 1144 1192 .read = snd_mixart_BA1_read, 1145 - .llseek = snd_mixart_BA1_llseek 1146 1193 }; 1147 1194 1148 1195