From ae76148114aa2457baa0d340fc506bb7d114cb12 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 23 Mar 2010 04:12:38 +0100 Subject: ALSA: aureon - Patch for suspend/resume for Terratec Aureon cards. Add proper suspend/resume code for Terratec Aureon cards. Based on ice1724 suspend/resume work of Igor Chernyshev. Fixes bug https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4944 Tested on linux-2.6.32.9 Signed-off-by: Bernhard Urban Signed-off-by: Takashi Iwai --- sound/pci/ice1712/aureon.c | 89 +++++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 25 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 9e66f6d306f..2f6252266a0 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1956,11 +1956,10 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice) return 0; } - /* - * initialize the chip + * reset the chip */ -static int __devinit aureon_init(struct snd_ice1712 *ice) +static int aureon_reset(struct snd_ice1712 *ice) { static const unsigned short wm_inits_aureon[] = { /* These come first to reduce init pop noise */ @@ -2047,30 +2046,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ (unsigned short)-1 }; - struct aureon_spec *spec; unsigned int tmp; const unsigned short *p; - int err, i; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - } else { - /* aureon 7.1 and prodigy 7.1 */ - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - } - - /* to remeber the register values of CS8415 */ - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (!ice->akm) - return -ENOMEM; - ice->akm_codecs = 1; + int err; + struct aureon_spec *spec = ice->spec; err = aureon_ac97_init(ice); if (err != 0) @@ -2118,6 +2097,61 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) /* initialize PCA9554 pin directions & set default input */ aureon_pca9554_write(ice, PCA9554_DIR, 0x00); aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ + return 0; +} + +/* + * suspend/resume + */ +#ifdef CONFIG_PM +static int aureon_resume(struct snd_ice1712 *ice) +{ + struct aureon_spec *spec = ice->spec; + int err, i; + + err = aureon_reset(ice); + if (err != 0) + return err; + + /* workaround for poking volume with alsamixer after resume: + * just set stored volume again */ + for (i = 0; i < ice->num_total_dacs; i++) + wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); + return 0; +} +#endif + +/* + * initialize the chip + */ +static int __devinit aureon_init(struct snd_ice1712 *ice) +{ + struct aureon_spec *spec; + int i, err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + ice->spec = spec; + + if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { + ice->num_total_dacs = 6; + ice->num_total_adcs = 2; + } else { + /* aureon 7.1 and prodigy 7.1 */ + ice->num_total_dacs = 8; + ice->num_total_adcs = 2; + } + + /* to remeber the register values of CS8415 */ + ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); + if (!ice->akm) + return -ENOMEM; + ice->akm_codecs = 1; + + err = aureon_reset(ice); + if (err != 0) + return err; spec->master[0] = WM_VOL_MUTE; spec->master[1] = WM_VOL_MUTE; @@ -2126,6 +2160,11 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); } +#ifdef CONFIG_PM + ice->pm_resume = aureon_resume; + ice->pm_suspend_enabled = 1; +#endif + return 0; } -- cgit v1.2.3 From 24e4a1211f691fc671de44685430dbad757d8487 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Apr 2010 11:22:01 +0200 Subject: ALSA: info - Use standard types for info callbacks Use loff_t, size_t and ssize_t for arguments of info callbacks to follow the standard procfs. Signed-off-by: Takashi Iwai --- include/sound/info.h | 24 ++++++++++++------------ sound/drivers/opl4/opl4_proc.c | 21 +++++++++++++-------- sound/isa/gus/gus_mem_proc.c | 16 ++++++++-------- sound/pci/cs4281.c | 16 ++++++++-------- sound/pci/cs46xx/cs46xx_lib.c | 7 ++++--- sound/pci/emu10k1/emuproc.c | 8 ++++---- sound/pci/mixart/mixart.c | 32 ++++++++++++++++---------------- 7 files changed, 65 insertions(+), 59 deletions(-) (limited to 'sound/pci') diff --git a/include/sound/info.h b/include/sound/info.h index 112e8949e1a..4e94cf1ff76 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -51,18 +51,18 @@ struct snd_info_entry_ops { unsigned short mode, void **file_private_data); int (*release)(struct snd_info_entry *entry, unsigned short mode, void *file_private_data); - long (*read)(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos); - long (*write)(struct snd_info_entry *entry, void *file_private_data, - struct file *file, const char __user *buf, - unsigned long count, unsigned long pos); - long long (*llseek)(struct snd_info_entry *entry, - void *file_private_data, struct file *file, - long long offset, int orig); - unsigned int(*poll)(struct snd_info_entry *entry, - void *file_private_data, struct file *file, - poll_table *wait); + ssize_t (*read)(struct snd_info_entry *entry, void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos); + ssize_t (*write)(struct snd_info_entry *entry, void *file_private_data, + struct file *file, const char __user *buf, + size_t count, loff_t pos); + loff_t (*llseek)(struct snd_info_entry *entry, + void *file_private_data, struct file *file, + loff_t offset, int orig); + unsigned int (*poll)(struct snd_info_entry *entry, + void *file_private_data, struct file *file, + poll_table *wait); int (*ioctl)(struct snd_info_entry *entry, void *file_private_data, struct file *file, unsigned int cmd, unsigned long arg); int (*mmap)(struct snd_info_entry *entry, void *file_private_data, diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index 1679300b758..eb72814dfd5 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -49,9 +49,10 @@ static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, return 0; } -static long snd_opl4_mem_proc_read(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *_buf, - unsigned long count, unsigned long pos) +static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *_buf, + size_t count, loff_t pos) { struct snd_opl4 *opl4 = entry->private_data; long size; @@ -75,9 +76,11 @@ static long snd_opl4_mem_proc_read(struct snd_info_entry *entry, void *file_priv return 0; } -static long snd_opl4_mem_proc_write(struct snd_info_entry *entry, void *file_private_data, - struct file *file, const char __user *_buf, - unsigned long count, unsigned long pos) +static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + const char __user *_buf, + size_t count, size_t pos) { struct snd_opl4 *opl4 = entry->private_data; long size; @@ -101,8 +104,10 @@ static long snd_opl4_mem_proc_write(struct snd_info_entry *entry, void *file_pri return 0; } -static long long snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, void *file_private_data, - struct file *file, long long offset, int orig) +static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + loff_t offset, int orig) { switch (orig) { case SEEK_SET: diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 2803e227aec..b2d2dba6c86 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c @@ -31,9 +31,10 @@ struct gus_proc_private { struct snd_gus_card * gus; }; -static long snd_gf1_mem_proc_dump(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { long size; struct gus_proc_private *priv = entry->private_data; @@ -51,11 +52,10 @@ static long snd_gf1_mem_proc_dump(struct snd_info_entry *entry, void *file_priva return 0; } -static long long snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - long long offset, - int orig) +static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, + void *private_file_data, + struct file *file, + loff_t offset, int orig) { struct gus_proc_private *priv = entry->private_data; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 9edc65059e3..b0bba2e86b1 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1139,10 +1139,10 @@ static void snd_cs4281_proc_read(struct snd_info_entry *entry, snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq); } -static long snd_cs4281_BA0_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { long size; struct cs4281 *chip = entry->private_data; @@ -1157,10 +1157,10 @@ static long snd_cs4281_BA0_read(struct snd_info_entry *entry, return size; } -static long snd_cs4281_BA1_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { long size; struct cs4281 *chip = entry->private_data; diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 3f99a5e8528..08117b14238 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2657,9 +2657,10 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } * proc interface */ -static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { long size; struct snd_cs46xx_region *region = entry->private_data; diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index baa7cd508cd..347b2415db5 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -341,10 +341,10 @@ static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry, #define TOTAL_SIZE_CODE (0x200*8) #define A_TOTAL_SIZE_CODE (0x400*8) -static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { long size; struct snd_emu10k1 *emu = entry->private_data; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 3be8f97c8bc..b5df78bcc25 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1102,11 +1102,10 @@ static int snd_mixart_free(struct mixart_mgr *mgr) /* * proc interface */ -static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - long long offset, - int orig) +static loff_t snd_mixart_BA0_llseek(struct snd_info_entry *entry, + void *private_file_data, + struct file *file, + loff_t offset, int orig) { offset = offset & ~3; /* 4 bytes aligned */ @@ -1128,11 +1127,10 @@ static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry, return file->f_pos; } -static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - long long offset, - int orig) +static loff_t snd_mixart_BA1_llseek(struct snd_info_entry *entry, + void *private_file_data, + struct file *file, + loff_t offset, int orig) { offset = offset & ~3; /* 4 bytes aligned */ @@ -1157,9 +1155,10 @@ static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry, /* mixart_BA0 proc interface for BAR 0 - read callback */ -static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { struct mixart_mgr *mgr = entry->private_data; unsigned long maxsize; @@ -1178,9 +1177,10 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private /* mixart_BA1 proc interface for BAR 1 - read callback */ -static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private_data, - struct file *file, char __user *buf, - unsigned long count, unsigned long pos) +static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *buf, + size_t count, loff_t pos) { struct mixart_mgr *mgr = entry->private_data; unsigned long maxsize; -- cgit v1.2.3 From d97e1b78239c7e7e441088e0b644bd3b076002e6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Apr 2010 11:33:54 +0200 Subject: ALSA: info - Check file position validity in common layer Check the validity of the file position in the common info layer before calling read or write callbacks in assumption that entry->size is set up properly to indicate the max file size. Removed the redundant checks from the callbacks as well. Signed-off-by: Takashi Iwai --- sound/core/info.c | 14 ++++++++++--- sound/drivers/opl4/opl4_proc.c | 46 +++++++++++++++--------------------------- sound/isa/gus/gus_mem_proc.c | 14 ++++--------- sound/pci/cs4281.c | 24 ++++++---------------- sound/pci/cs46xx/cs46xx_lib.c | 12 +++-------- sound/pci/emu10k1/emuproc.c | 43 ++++++++++++++++++--------------------- sound/pci/mixart/mixart.c | 12 ----------- 7 files changed, 60 insertions(+), 105 deletions(-) (limited to 'sound/pci') diff --git a/sound/core/info.c b/sound/core/info.c index ff968be8167..f90a6fd43fb 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -232,10 +232,15 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, return -EFAULT; break; case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->read) + if (pos >= entry->size) + return 0; + if (entry->c.ops->read) { + size = entry->size - pos; + size = min(count, size); size = entry->c.ops->read(entry, data->file_private_data, - file, buffer, count, pos); + file, buffer, size, pos); + } break; } if ((ssize_t) size > 0) @@ -282,10 +287,13 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer size = count; break; case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->write) + if (entry->c.ops->write && count > 0) { + size_t maxsize = entry->size - pos; + count = min(count, maxsize); size = entry->c.ops->write(entry, data->file_private_data, file, buffer, count, pos); + } break; } if ((ssize_t) size > 0) diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index eb72814dfd5..210b89de06d 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -55,25 +55,18 @@ static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, size_t count, loff_t pos) { struct snd_opl4 *opl4 = entry->private_data; - long size; char* buf; - size = count; - if (pos + size > entry->size) - size = entry->size - pos; - if (size > 0) { - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - snd_opl4_read_memory(opl4, buf, pos, size); - if (copy_to_user(_buf, buf, size)) { - vfree(buf); - return -EFAULT; - } + buf = vmalloc(count); + if (!buf) + return -ENOMEM; + snd_opl4_read_memory(opl4, buf, pos, count); + if (copy_to_user(_buf, buf, count)) { vfree(buf); - return size; + return -EFAULT; } - return 0; + vfree(buf); + return count; } static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, @@ -83,25 +76,18 @@ static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, size_t count, size_t pos) { struct snd_opl4 *opl4 = entry->private_data; - long size; char *buf; - size = count; - if (pos + size > entry->size) - size = entry->size - pos; - if (size > 0) { - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - if (copy_from_user(buf, _buf, size)) { - vfree(buf); - return -EFAULT; - } - snd_opl4_write_memory(opl4, buf, pos, size); + buf = vmalloc(count); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, _buf, count)) { vfree(buf); - return size; + return -EFAULT; } - return 0; + snd_opl4_write_memory(opl4, buf, pos, count); + vfree(buf); + return count; } static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index b2d2dba6c86..faa2bec8f6b 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c @@ -36,20 +36,14 @@ static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry, struct file *file, char __user *buf, size_t count, loff_t pos) { - long size; struct gus_proc_private *priv = entry->private_data; struct snd_gus_card *gus = priv->gus; int err; - size = count; - if (pos + size > priv->size) - size = (long)priv->size - pos; - if (size > 0) { - if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0) - return err; - return size; - } - return 0; + err = snd_gus_dram_read(gus, buf, pos, count, priv->rom); + if (err < 0) + return err; + return count; } static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index b0bba2e86b1..6772070ed49 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1144,17 +1144,11 @@ static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry, struct file *file, char __user *buf, size_t count, loff_t pos) { - long size; struct cs4281 *chip = entry->private_data; - size = count; - if (pos + size > CS4281_BA0_SIZE) - size = (long)CS4281_BA0_SIZE - pos; - if (size > 0) { - if (copy_to_user_fromio(buf, chip->ba0 + pos, size)) - return -EFAULT; - } - return size; + if (copy_to_user_fromio(buf, chip->ba0 + pos, count)) + return -EFAULT; + return count; } static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, @@ -1162,17 +1156,11 @@ static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, struct file *file, char __user *buf, size_t count, loff_t pos) { - long size; struct cs4281 *chip = entry->private_data; - size = count; - if (pos + size > CS4281_BA1_SIZE) - size = (long)CS4281_BA1_SIZE - pos; - if (size > 0) { - if (copy_to_user_fromio(buf, chip->ba1 + pos, size)) - return -EFAULT; - } - return size; + if (copy_to_user_fromio(buf, chip->ba1 + pos, count)) + return -EFAULT; + return count; } static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 08117b14238..aad37082cb6 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2662,17 +2662,11 @@ static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry, struct file *file, char __user *buf, size_t count, loff_t pos) { - long size; struct snd_cs46xx_region *region = entry->private_data; - size = count; - if (pos + (size_t)size > region->size) - size = region->size - pos; - if (size > 0) { - if (copy_to_user_fromio(buf, region->remap_addr + pos, size)) - return -EFAULT; - } - return size; + if (copy_to_user_fromio(buf, region->remap_addr + pos, count)) + return -EFAULT; + return count; } static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 347b2415db5..bc38dd4d071 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -346,10 +346,12 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, struct file *file, char __user *buf, size_t count, loff_t pos) { - long size; struct snd_emu10k1 *emu = entry->private_data; unsigned int offset; int tram_addr = 0; + unsigned int *tmp; + long res; + unsigned int idx; if (!strcmp(entry->name, "fx8010_tram_addr")) { offset = TANKMEMADDRREGBASE; @@ -361,30 +363,25 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, } else { offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; } - size = count; - if (pos + size > entry->size) - size = (long)entry->size - pos; - if (size > 0) { - unsigned int *tmp; - long res; - unsigned int idx; - if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL) - return -ENOMEM; - for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++) - if (tram_addr && emu->audigy) { - tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11; - tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; - } else - tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); - if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size)) - res = -EFAULT; - else { - res = size; + + tmp = kmalloc(count + 8, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) { + unsigned int val; + val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); + if (tram_addr && emu->audigy) { + val >>= 11; + val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; } - kfree(tmp); - return res; + tmp[idx] = val; } - return 0; + if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count)) + res = -EFAULT; + else + res = count; + kfree(tmp); + return res; } static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index b5df78bcc25..be95e005c81 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1161,13 +1161,7 @@ static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry, size_t count, loff_t pos) { struct mixart_mgr *mgr = entry->private_data; - unsigned long maxsize; - if (pos >= MIXART_BA0_SIZE) - return 0; - maxsize = MIXART_BA0_SIZE - pos; - if (count > maxsize) - count = maxsize; count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) return -EFAULT; @@ -1183,13 +1177,7 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, size_t count, loff_t pos) { struct mixart_mgr *mgr = entry->private_data; - unsigned long maxsize; - if (pos > MIXART_BA1_SIZE) - return 0; - maxsize = MIXART_BA1_SIZE - pos; - if (count > maxsize) - count = maxsize; count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) return -EFAULT; -- cgit v1.2.3 From 73029e0ff18dfac8a1aab1dc188e1e150bbe3adc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Apr 2010 11:39:47 +0200 Subject: 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 --- sound/core/info.c | 56 ++++++++++++++++++++++-------------------- sound/drivers/opl4/opl4_proc.c | 24 ------------------ sound/isa/gus/gus_mem_proc.c | 26 -------------------- sound/pci/mixart/mixart.c | 51 -------------------------------------- 4 files changed, 30 insertions(+), 127 deletions(-) (limited to 'sound/pci') diff --git a/sound/core/info.c b/sound/core/info.c index f90a6fd43fb..b70564ed8b3 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -164,39 +164,43 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) { struct snd_info_private_data *data; struct snd_info_entry *entry; - loff_t ret; + loff_t ret = -EINVAL, size; data = file->private_data; entry = data->entry; mutex_lock(&entry->access); - switch (entry->content) { - case SNDRV_INFO_CONTENT_TEXT: - switch (orig) { - case SEEK_SET: - file->f_pos = offset; - ret = file->f_pos; - goto out; - case SEEK_CUR: - file->f_pos += offset; - ret = file->f_pos; - goto out; - case SEEK_END: - default: - ret = -EINVAL; - goto out; - } + if (entry->content == SNDRV_INFO_CONTENT_DATA && + entry->c.ops->llseek) { + offset = entry->c.ops->llseek(entry, + data->file_private_data, + file, offset, orig); + goto out; + } + if (entry->content == SNDRV_INFO_CONTENT_DATA) + size = entry->size; + else + size = 0; + switch (orig) { + case SEEK_SET: break; - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->llseek) { - ret = entry->c.ops->llseek(entry, - data->file_private_data, - file, offset, orig); + case SEEK_CUR: + offset += file->f_pos; + break; + case SEEK_END: + if (!size) goto out; - } + offset += size; break; - } - ret = -ENXIO; -out: + default: + goto out; + } + if (offset < 0) + goto out; + if (size && offset > size) + offset = size; + file->f_pos = offset; + ret = offset; + out: mutex_unlock(&entry->access); return ret; } diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index 210b89de06d..c5c13c4c260 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -90,35 +90,11 @@ static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, return count; } -static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, - loff_t offset, int orig) -{ - switch (orig) { - case SEEK_SET: - file->f_pos = offset; - break; - case SEEK_CUR: - file->f_pos += offset; - break; - case SEEK_END: /* offset is negative */ - file->f_pos = entry->size + offset; - break; - default: - return -EINVAL; - } - if (file->f_pos > entry->size) - file->f_pos = entry->size; - return file->f_pos; -} - static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { .open = snd_opl4_mem_proc_open, .release = snd_opl4_mem_proc_release, .read = snd_opl4_mem_proc_read, .write = snd_opl4_mem_proc_write, - .llseek = snd_opl4_mem_proc_llseek, }; int snd_opl4_create_proc(struct snd_opl4 *opl4) diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index faa2bec8f6b..2ccb3fadd7b 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c @@ -46,31 +46,6 @@ static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry, return count; } -static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - loff_t offset, int orig) -{ - struct gus_proc_private *priv = entry->private_data; - - switch (orig) { - case SEEK_SET: - file->f_pos = offset; - break; - case SEEK_CUR: - file->f_pos += offset; - break; - case SEEK_END: /* offset is negative */ - file->f_pos = priv->size + offset; - break; - default: - return -EINVAL; - } - if (file->f_pos > priv->size) - file->f_pos = priv->size; - return file->f_pos; -} - static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) { struct gus_proc_private *priv = entry->private_data; @@ -79,7 +54,6 @@ static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) static struct snd_info_entry_ops snd_gf1_mem_proc_ops = { .read = snd_gf1_mem_proc_dump, - .llseek = snd_gf1_mem_proc_llseek, }; int snd_gf1_mem_proc_init(struct snd_gus_card * gus) diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index be95e005c81..6c3fd4d1c49 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1102,55 +1102,6 @@ static int snd_mixart_free(struct mixart_mgr *mgr) /* * proc interface */ -static loff_t snd_mixart_BA0_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - loff_t offset, int orig) -{ - offset = offset & ~3; /* 4 bytes aligned */ - - switch(orig) { - case SEEK_SET: - file->f_pos = offset; - break; - case SEEK_CUR: - file->f_pos += offset; - break; - case SEEK_END: /* offset is negative */ - file->f_pos = MIXART_BA0_SIZE + offset; - break; - default: - return -EINVAL; - } - if(file->f_pos > MIXART_BA0_SIZE) - file->f_pos = MIXART_BA0_SIZE; - return file->f_pos; -} - -static loff_t snd_mixart_BA1_llseek(struct snd_info_entry *entry, - void *private_file_data, - struct file *file, - loff_t offset, int orig) -{ - offset = offset & ~3; /* 4 bytes aligned */ - - switch(orig) { - case SEEK_SET: - file->f_pos = offset; - break; - case SEEK_CUR: - file->f_pos += offset; - break; - case SEEK_END: /* offset is negative */ - file->f_pos = MIXART_BA1_SIZE + offset; - break; - default: - return -EINVAL; - } - if(file->f_pos > MIXART_BA1_SIZE) - file->f_pos = MIXART_BA1_SIZE; - return file->f_pos; -} /* mixart_BA0 proc interface for BAR 0 - read callback @@ -1186,12 +1137,10 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { .read = snd_mixart_BA0_read, - .llseek = snd_mixart_BA0_llseek }; static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { .read = snd_mixart_BA1_read, - .llseek = snd_mixart_BA1_llseek }; -- cgit v1.2.3