git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Use f_lock to protect f_flags
[safe/jmp/linux-2.6]
/
sound
/
oss
/
au1550_ac97.c
diff --git
a/sound/oss/au1550_ac97.c
b/sound/oss/au1550_ac97.c
index
a78e48d
..
4191acc
100644
(file)
--- a/
sound/oss/au1550_ac97.c
+++ b/
sound/oss/au1550_ac97.c
@@
-35,7
+35,6
@@
#undef DEBUG
#undef DEBUG
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/ioport.h>
@@
-48,17
+47,18
@@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/poll.h>
-#include <linux/pci.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
+#include <linux/mutex.h>
+
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
-#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx.h>
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
@@
-78,7
+78,7
@@
* 0 = no VRA, 1 = use VRA if codec supports it
*/
static int vra = 1;
* 0 = no VRA, 1 = use VRA if codec supports it
*/
static int vra = 1;
-
MODULE_PARM(vra, "i"
);
+
module_param(vra, bool, 0
);
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
static struct au1550_state {
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
static struct au1550_state {
@@
-91,9
+91,9
@@
static struct au1550_state {
int no_vra; /* do not use VRA */
spinlock_t lock;
int no_vra; /* do not use VRA */
spinlock_t lock;
- struct
semaphore open_sem
;
- struct
semaphore
sem;
- mode_t open_mode;
+ struct
mutex open_mutex
;
+ struct
mutex
sem;
+
f
mode_t open_mode;
wait_queue_head_t open_wait;
struct dmabuf {
wait_queue_head_t open_wait;
struct dmabuf {
@@
-212,7
+212,8
@@
rdcodec(struct ac97_codec *codec, u8 addr)
}
if (i == POLL_COUNT) {
err("rdcodec: read poll expired!");
}
if (i == POLL_COUNT) {
err("rdcodec: read poll expired!");
- return 0;
+ data = 0;
+ goto out;
}
/* wait for command done?
}
/* wait for command done?
@@
-225,7
+226,8
@@
rdcodec(struct ac97_codec *codec, u8 addr)
}
if (i == POLL_COUNT) {
err("rdcodec: read cmdwait expired!");
}
if (i == POLL_COUNT) {
err("rdcodec: read cmdwait expired!");
- return 0;
+ data = 0;
+ goto out;
}
data = au_readl(PSC_AC97CDC) & 0xffff;
}
data = au_readl(PSC_AC97CDC) & 0xffff;
@@
-236,6
+238,7
@@
rdcodec(struct ac97_codec *codec, u8 addr)
au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
au_sync();
au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
au_sync();
+ out:
spin_unlock_irqrestore(&s->lock, flags);
return data;
spin_unlock_irqrestore(&s->lock, flags);
return data;
@@
-463,7
+466,7
@@
stop_dac(struct au1550_state *s)
/* Wait for Transmit Busy to show disabled.
*/
do {
/* Wait for Transmit Busy to show disabled.
*/
do {
- stat =
readl((void *)
PSC_AC97STAT);
+ stat =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_TB) != 0);
au_sync();
} while ((stat & PSC_AC97STAT_TB) != 0);
@@
-492,7
+495,7
@@
stop_adc(struct au1550_state *s)
/* Wait for Receive Busy to show disabled.
*/
do {
/* Wait for Receive Busy to show disabled.
*/
do {
- stat =
readl((void *)
PSC_AC97STAT);
+ stat =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_RB) != 0);
au_sync();
} while ((stat & PSC_AC97STAT_RB) != 0);
@@
-542,7
+545,7
@@
set_xmit_slots(int num_channels)
/* Wait for Device ready.
*/
do {
/* Wait for Device ready.
*/
do {
- stat =
readl((void *)
PSC_AC97STAT);
+ stat =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
@@
-574,22
+577,20
@@
set_recv_slots(int num_channels)
/* Wait for Device ready.
*/
do {
/* Wait for Device ready.
*/
do {
- stat =
readl((void *)
PSC_AC97STAT);
+ stat =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
+/* Hold spinlock for both start_dac() and start_adc() calls */
static void
start_dac(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_dac;
static void
start_dac(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_dac;
- unsigned long flags;
if (!db->stopped)
return;
if (!db->stopped)
return;
- spin_lock_irqsave(&s->lock, flags);
-
set_xmit_slots(db->num_channels);
au_writel(PSC_AC97PCR_TC, PSC_AC97PCR);
au_sync();
set_xmit_slots(db->num_channels);
au_writel(PSC_AC97PCR_TC, PSC_AC97PCR);
au_sync();
@@
-599,8
+600,6
@@
start_dac(struct au1550_state *s)
au1xxx_dbdma_start(db->dmanr);
db->stopped = 0;
au1xxx_dbdma_start(db->dmanr);
db->stopped = 0;
-
- spin_unlock_irqrestore(&s->lock, flags);
}
static void
}
static void
@@
-719,14
+718,14
@@
prog_dmabuf_dac(struct au1550_state *s)
}
}
-/* hold spinlock for the following */
-static void
-dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void dac_dma_interrupt(int irq, void *dev_id)
{
struct au1550_state *s = (struct au1550_state *) dev_id;
struct dmabuf *db = &s->dma_dac;
u32 ac97c_stat;
{
struct au1550_state *s = (struct au1550_state *) dev_id;
struct dmabuf *db = &s->dma_dac;
u32 ac97c_stat;
+ spin_lock(&s->lock);
+
ac97c_stat = au_readl(PSC_AC97STAT);
if (ac97c_stat & (AC97C_XU | AC97C_XO | AC97C_TE))
pr_debug("AC97C status = 0x%08x\n", ac97c_stat);
ac97c_stat = au_readl(PSC_AC97STAT);
if (ac97c_stat & (AC97C_XU | AC97C_XO | AC97C_TE))
pr_debug("AC97C status = 0x%08x\n", ac97c_stat);
@@
-748,17
+747,20
@@
dac_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* wake up anybody listening */
if (waitqueue_active(&db->wait))
wake_up(&db->wait);
/* wake up anybody listening */
if (waitqueue_active(&db->wait))
wake_up(&db->wait);
+
+ spin_unlock(&s->lock);
}
}
-static void
-adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void adc_dma_interrupt(int irq, void *dev_id)
{
struct au1550_state *s = (struct au1550_state *)dev_id;
struct dmabuf *dp = &s->dma_adc;
u32 obytes;
char *obuf;
{
struct au1550_state *s = (struct au1550_state *)dev_id;
struct dmabuf *dp = &s->dma_adc;
u32 obytes;
char *obuf;
+ spin_lock(&s->lock);
+
/* Pull the buffer from the dma queue.
*/
au1xxx_dbdma_get_dest(dp->dmanr, (void *)(&obuf), &obytes);
/* Pull the buffer from the dma queue.
*/
au1xxx_dbdma_get_dest(dp->dmanr, (void *)(&obuf), &obytes);
@@
-766,6
+768,7
@@
adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if ((dp->count + obytes) > dp->dmasize) {
/* Overrun. Stop ADC and log the error
*/
if ((dp->count + obytes) > dp->dmasize) {
/* Overrun. Stop ADC and log the error
*/
+ spin_unlock(&s->lock);
stop_adc(s);
dp->error++;
err("adc overrun");
stop_adc(s);
dp->error++;
err("adc overrun");
@@
-788,6
+791,7
@@
adc_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (waitqueue_active(&dp->wait))
wake_up(&dp->wait);
if (waitqueue_active(&dp->wait))
wake_up(&dp->wait);
+ spin_unlock(&s->lock);
}
static loff_t
}
static loff_t
@@
-1042,16
+1046,16
@@
au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
count *= db->cnt_factor;
count *= db->cnt_factor;
-
down
(&s->sem);
+
mutex_lock
(&s->sem);
add_wait_queue(&db->wait, &wait);
while (count > 0) {
/* wait for samples in ADC dma buffer
*/
do {
add_wait_queue(&db->wait, &wait);
while (count > 0) {
/* wait for samples in ADC dma buffer
*/
do {
+ spin_lock_irqsave(&s->lock, flags);
if (db->stopped)
start_adc(s);
if (db->stopped)
start_adc(s);
- spin_lock_irqsave(&s->lock, flags);
avail = db->count;
if (avail <= 0)
__set_current_state(TASK_INTERRUPTIBLE);
avail = db->count;
if (avail <= 0)
__set_current_state(TASK_INTERRUPTIBLE);
@@
-1062,14
+1066,14
@@
au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
ret = -EAGAIN;
goto out;
}
ret = -EAGAIN;
goto out;
}
-
up
(&s->sem);
+
mutex_unlock
(&s->sem);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
-
down
(&s->sem);
+
mutex_lock
(&s->sem);
}
} while (avail <= 0);
}
} while (avail <= 0);
@@
-1097,7
+1101,7
@@
au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
} /* while (count > 0) */
out:
} /* while (count > 0) */
out:
-
up
(&s->sem);
+
mutex_unlock
(&s->sem);
out2:
remove_wait_queue(&db->wait, &wait);
set_current_state(TASK_RUNNING);
out2:
remove_wait_queue(&db->wait, &wait);
set_current_state(TASK_RUNNING);
@@
-1123,7
+1127,7
@@
au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
count *= db->cnt_factor;
count *= db->cnt_factor;
-
down
(&s->sem);
+
mutex_lock
(&s->sem);
add_wait_queue(&db->wait, &wait);
while (count > 0) {
add_wait_queue(&db->wait, &wait);
while (count > 0) {
@@
-1141,14
+1145,14
@@
au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
ret = -EAGAIN;
goto out;
}
ret = -EAGAIN;
goto out;
}
-
up
(&s->sem);
+
mutex_unlock
(&s->sem);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
-
down
(&s->sem);
+
mutex_lock
(&s->sem);
}
} while (avail <= 0);
}
} while (avail <= 0);
@@
-1194,7
+1198,7
@@
au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
} /* while (count > 0) */
out:
} /* while (count > 0) */
out:
-
up
(&s->sem);
+
mutex_unlock
(&s->sem);
out2:
remove_wait_queue(&db->wait, &wait);
set_current_state(TASK_RUNNING);
out2:
remove_wait_queue(&db->wait, &wait);
set_current_state(TASK_RUNNING);
@@
-1251,7
+1255,7
@@
au1550_mmap(struct file *file, struct vm_area_struct *vma)
int ret = 0;
lock_kernel();
int ret = 0;
lock_kernel();
-
down
(&s->sem);
+
mutex_lock
(&s->sem);
if (vma->vm_flags & VM_WRITE)
db = &s->dma_dac;
else if (vma->vm_flags & VM_READ)
if (vma->vm_flags & VM_WRITE)
db = &s->dma_dac;
else if (vma->vm_flags & VM_READ)
@@
-1277,7
+1281,7
@@
au1550_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags &= ~VM_IO;
db->mapped = 1;
out:
vma->vm_flags &= ~VM_IO;
db->mapped = 1;
out:
-
up
(&s->sem);
+
mutex_unlock
(&s->sem);
unlock_kernel();
return ret;
}
unlock_kernel();
return ret;
}
@@
-1349,11
+1353,11
@@
au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
#ifdef DEBUG
((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
#ifdef DEBUG
- for (count
=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]
); count++) {
+ for (count
= 0; count < ARRAY_SIZE(ioctl_str
); count++) {
if (ioctl_str[count].cmd == cmd)
break;
}
if (ioctl_str[count].cmd == cmd)
break;
}
- if (count <
sizeof(ioctl_str) / sizeof(ioctl_str[0]
))
+ if (count <
ARRAY_SIZE(ioctl_str
))
pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg);
else
pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg);
pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg);
else
pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg);
@@
-1571,15
+1575,19
@@
au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (get_user(val, (int *) arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (get_user(val, (int *) arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
- if (val & PCM_ENABLE_INPUT)
+ if (val & PCM_ENABLE_INPUT) {
+ spin_lock_irqsave(&s->lock, flags);
start_adc(s);
start_adc(s);
- else
+ spin_unlock_irqrestore(&s->lock, flags);
+ } else
stop_adc(s);
}
if (file->f_mode & FMODE_WRITE) {
stop_adc(s);
}
if (file->f_mode & FMODE_WRITE) {
- if (val & PCM_ENABLE_OUTPUT)
+ if (val & PCM_ENABLE_OUTPUT) {
+ spin_lock_irqsave(&s->lock, flags);
start_dac(s);
start_dac(s);
- else
+ spin_unlock_irqrestore(&s->lock, flags);
+ } else
stop_dac(s);
}
return 0;
stop_dac(s);
}
return 0;
@@
-1619,7
+1627,9
@@
au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
sizeof(abinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_NONBLOCK:
sizeof(abinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_NONBLOCK:
+ spin_lock(&file->f_lock);
file->f_flags |= O_NONBLOCK;
file->f_flags |= O_NONBLOCK;
+ spin_unlock(&file->f_lock);
return 0;
case SNDCTL_DSP_GETODELAY:
return 0;
case SNDCTL_DSP_GETODELAY:
@@
-1784,21
+1794,21
@@
au1550_open(struct inode *inode, struct file *file)
file->private_data = s;
/* wait for device to become free */
file->private_data = s;
/* wait for device to become free */
-
down(&s->open_sem
);
+
mutex_lock(&s->open_mutex
);
while (s->open_mode & file->f_mode) {
if (file->f_flags & O_NONBLOCK) {
while (s->open_mode & file->f_mode) {
if (file->f_flags & O_NONBLOCK) {
-
up(&s->open_sem
);
+
mutex_unlock(&s->open_mutex
);
return -EBUSY;
}
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
return -EBUSY;
}
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
-
up(&s->open_sem
);
+
mutex_unlock(&s->open_mutex
);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
-
down(&s->open_sem
);
+
mutex_lock(&s->open_mutex
);
}
stop_dac(s);
}
stop_dac(s);
@@
-1834,8
+1844,8
@@
au1550_open(struct inode *inode, struct file *file)
}
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
}
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-
up(&s->open_sem
);
-
init_MUTEX
(&s->sem);
+
mutex_unlock(&s->open_mutex
);
+
mutex_init
(&s->sem);
return 0;
}
return 0;
}
@@
-1852,7
+1862,7
@@
au1550_release(struct inode *inode, struct file *file)
lock_kernel();
}
lock_kernel();
}
-
down(&s->open_sem
);
+
mutex_lock(&s->open_mutex
);
if (file->f_mode & FMODE_WRITE) {
stop_dac(s);
kfree(s->dma_dac.rawbuf);
if (file->f_mode & FMODE_WRITE) {
stop_dac(s);
kfree(s->dma_dac.rawbuf);
@@
-1864,7
+1874,7
@@
au1550_release(struct inode *inode, struct file *file)
s->dma_adc.rawbuf = NULL;
}
s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
s->dma_adc.rawbuf = NULL;
}
s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
-
up(&s->open_sem
);
+
mutex_unlock(&s->open_mutex
);
wake_up(&s->open_wait);
unlock_kernel();
return 0;
wake_up(&s->open_wait);
unlock_kernel();
return 0;
@@
-1884,6
+1894,8
@@
static /*const */ struct file_operations au1550_audio_fops = {
MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
MODULE_DESCRIPTION("Au1550 AC97 Audio Driver");
MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
MODULE_DESCRIPTION("Au1550 AC97 Audio Driver");
+MODULE_LICENSE("GPL");
+
static int __devinit
au1550_probe(void)
static int __devinit
au1550_probe(void)
@@
-1896,7
+1908,7
@@
au1550_probe(void)
init_waitqueue_head(&s->dma_adc.wait);
init_waitqueue_head(&s->dma_dac.wait);
init_waitqueue_head(&s->open_wait);
init_waitqueue_head(&s->dma_adc.wait);
init_waitqueue_head(&s->dma_dac.wait);
init_waitqueue_head(&s->open_wait);
-
init_MUTEX(&s->open_sem
);
+
mutex_init(&s->open_mutex
);
spin_lock_init(&s->lock);
s->codec = ac97_alloc_codec();
spin_lock_init(&s->lock);
s->codec = ac97_alloc_codec();
@@
-1989,7
+2001,7
@@
au1550_probe(void)
/* Wait for PSC ready.
*/
do {
/* Wait for PSC ready.
*/
do {
- val =
readl((void *)
PSC_AC97STAT);
+ val =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((val & PSC_AC97STAT_SR) == 0);
au_sync();
} while ((val & PSC_AC97STAT_SR) == 0);
@@
-2012,7
+2024,7
@@
au1550_probe(void)
/* Wait for Device ready.
*/
do {
/* Wait for Device ready.
*/
do {
- val =
readl((void *)
PSC_AC97STAT);
+ val =
au_readl(
PSC_AC97STAT);
au_sync();
} while ((val & PSC_AC97STAT_DR) == 0);
au_sync();
} while ((val & PSC_AC97STAT_DR) == 0);