aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorAlexander Viro <viro@parcelfarce.linux.theplanet.co.uk>2004-06-03 02:47:28 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-03 02:47:28 -0700
commite29b3d48f5cbaa4fa6255569e3204444fe205661 (patch)
tree78f0de522c28fa07a7e0705339225eae55d63df1 /sound
parentac1aff9920bd6f8b12972fc376bc41b64fa2cf4e (diff)
downloadhistory-e29b3d48f5cbaa4fa6255569e3204444fe205661.tar.gz
[PATCH] sparse: msnd sound fix
msnd_pinnacle/msnd_classic do copy_{to,from}_user under a spinlock. Taken out of spinlock (into a temp. buffer). Calls of msnd_fifo_{read,write} always go from kernel buffer now, so we can drop the 'int user' argument in them _and_ simplify error handling - all errors were from copy_..._user() and now these are called directly by dsp_read()/dsp_write().
Diffstat (limited to 'sound')
-rw-r--r--sound/oss/msnd.c22
-rw-r--r--sound/oss/msnd.h4
-rw-r--r--sound/oss/msnd_pinnacle.c88
3 files changed, 62 insertions, 52 deletions
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c
index 3fdbaf5f206385..6ccdd096f9183e 100644
--- a/sound/oss/msnd.c
+++ b/sound/oss/msnd.c
@@ -139,13 +139,10 @@ void msnd_fifo_make_empty(msnd_fifo *f)
f->len = f->tail = f->head = 0;
}
-int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user)
+int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len)
{
int count = 0;
- if (f->len == f->n)
- return 0;
-
while ((count < len) && (f->len != f->n)) {
int nwritten;
@@ -161,11 +158,7 @@ int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user)
nwritten = len - count;
}
- if (user) {
- if (copy_from_user(f->data + f->tail, buf, nwritten))
- return -EFAULT;
- } else
- isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten);
+ isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten);
count += nwritten;
buf += nwritten;
@@ -177,13 +170,10 @@ int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user)
return count;
}
-int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user)
+int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len)
{
int count = 0;
- if (f->len == 0)
- return f->len;
-
while ((count < len) && (f->len > 0)) {
int nread;
@@ -199,11 +189,7 @@ int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user)
nread = len - count;
}
- if (user) {
- if (copy_to_user(buf, f->data + f->head, nread))
- return -EFAULT;
- } else
- isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread);
+ isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread);
count += nread;
buf += nread;
diff --git a/sound/oss/msnd.h b/sound/oss/msnd.h
index 7b361921e6d08f..73148d2eefe78d 100644
--- a/sound/oss/msnd.h
+++ b/sound/oss/msnd.h
@@ -266,8 +266,8 @@ void msnd_fifo_init(msnd_fifo *f);
void msnd_fifo_free(msnd_fifo *f);
int msnd_fifo_alloc(msnd_fifo *f, size_t n);
void msnd_fifo_make_empty(msnd_fifo *f);
-int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user);
-int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user);
+int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len);
+int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len);
int msnd_wait_TXDE(multisound_dev_t *dev);
int msnd_wait_HC0(multisound_dev_t *dev);
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index aea4a65f78fb1d..16a918fb442c9d 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -809,7 +809,7 @@ static int dev_release(struct inode *inode, struct file *file)
static __inline__ int pack_DARQ_to_DARF(register int bank)
{
- register int size, n, timeout = 3;
+ register int size, timeout = 3;
register WORD wTmp;
LPDAQD DAQD;
@@ -830,13 +830,10 @@ static __inline__ int pack_DARQ_to_DARF(register int bank)
/* Read data from the head (unprotected bank 1 access okay
since this is only called inside an interrupt) */
outb(HPBLKSEL_1, dev.io + HP_BLKS);
- if ((n = msnd_fifo_write(
+ msnd_fifo_write(
&dev.DARF,
(char *)(dev.base + bank * DAR_BUFF_SIZE),
- size, 0)) <= 0) {
- outb(HPBLKSEL_0, dev.io + HP_BLKS);
- return n;
- }
+ size);
outb(HPBLKSEL_0, dev.io + HP_BLKS);
return 1;
@@ -858,21 +855,16 @@ static __inline__ int pack_DAPF_to_DAPQ(register int start)
if (protect) {
/* Critical section: protect fifo in non-interrupt */
spin_lock_irqsave(&dev.lock, flags);
- if ((n = msnd_fifo_read(
+ n = msnd_fifo_read(
&dev.DAPF,
(char *)(dev.base + bank_num * DAP_BUFF_SIZE),
- DAP_BUFF_SIZE, 0)) < 0) {
- spin_unlock_irqrestore(&dev.lock, flags);
- return n;
- }
+ DAP_BUFF_SIZE);
spin_unlock_irqrestore(&dev.lock, flags);
} else {
- if ((n = msnd_fifo_read(
+ n = msnd_fifo_read(
&dev.DAPF,
(char *)(dev.base + bank_num * DAP_BUFF_SIZE),
- DAP_BUFF_SIZE, 0)) < 0) {
- return n;
- }
+ DAP_BUFF_SIZE);
}
if (!n)
break;
@@ -899,30 +891,43 @@ static __inline__ int pack_DAPF_to_DAPQ(register int start)
static int dsp_read(char *buf, size_t len)
{
int count = len;
+ char *page = (char *)__get_free_page(PAGE_SIZE);
+
+ if (!page)
+ return -ENOMEM;
while (count > 0) {
- int n;
+ int n, k;
unsigned long flags;
+ k = PAGE_SIZE;
+ if (k > count)
+ k = count;
+
/* Critical section: protect fifo in non-interrupt */
spin_lock_irqsave(&dev.lock, flags);
- if ((n = msnd_fifo_read(&dev.DARF, buf, count, 1)) < 0) {
- printk(KERN_WARNING LOGNAME ": FIFO read error\n");
- spin_unlock_irqrestore(&dev.lock, flags);
- return n;
- }
+ n = msnd_fifo_read(&dev.DARF, page, k);
spin_unlock_irqrestore(&dev.lock, flags);
+ if (copy_to_user(buf, page, n)) {
+ free_page((unsigned long)page);
+ return -EFAULT;
+ }
buf += n;
count -= n;
+ if (n == k && count)
+ continue;
+
if (!test_bit(F_READING, &dev.flags) && dev.mode & FMODE_READ) {
dev.last_recbank = -1;
if (chk_send_dsp_cmd(&dev, HDEX_RECORD_START) == 0)
set_bit(F_READING, &dev.flags);
}
- if (dev.rec_ndelay)
+ if (dev.rec_ndelay) {
+ free_page((unsigned long)page);
return count == len ? -EAGAIN : len - count;
+ }
if (count > 0) {
set_bit(F_READBLOCK, &dev.flags);
@@ -931,41 +936,57 @@ static int dsp_read(char *buf, size_t len)
get_rec_delay_jiffies(DAR_BUFF_SIZE)))
clear_bit(F_READING, &dev.flags);
clear_bit(F_READBLOCK, &dev.flags);
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ free_page((unsigned long)page);
return -EINTR;
+ }
}
}
-
+ free_page((unsigned long)page);
return len - count;
}
static int dsp_write(const char *buf, size_t len)
{
int count = len;
+ char *page = (char *)__get_free_page(GFP_KERNEL);
+
+ if (!page)
+ return -ENOMEM;
while (count > 0) {
- int n;
+ int n, k;
unsigned long flags;
+ k = PAGE_SIZE;
+ if (k > count)
+ k = count;
+
+ if (copy_from_user(page, buf, k)) {
+ free_page((unsigned long)page);
+ return -EFAULT;
+ }
+
/* Critical section: protect fifo in non-interrupt */
spin_lock_irqsave(&dev.lock, flags);
- if ((n = msnd_fifo_write(&dev.DAPF, buf, count, 1)) < 0) {
- printk(KERN_WARNING LOGNAME ": FIFO write error\n");
- spin_unlock_irqrestore(&dev.lock, flags);
- return n;
- }
+ n = msnd_fifo_write(&dev.DAPF, page, k);
spin_unlock_irqrestore(&dev.lock, flags);
buf += n;
count -= n;
+ if (count && n == k)
+ continue;
+
if (!test_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) {
dev.last_playbank = -1;
if (pack_DAPF_to_DAPQ(1) > 0)
set_bit(F_WRITING, &dev.flags);
}
- if (dev.play_ndelay)
+ if (dev.play_ndelay) {
+ free_page((unsigned long)page);
return count == len ? -EAGAIN : len - count;
+ }
if (count > 0) {
set_bit(F_WRITEBLOCK, &dev.flags);
@@ -973,11 +994,14 @@ static int dsp_write(const char *buf, size_t len)
&dev.writeblock,
get_play_delay_jiffies(DAP_BUFF_SIZE));
clear_bit(F_WRITEBLOCK, &dev.flags);
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ free_page((unsigned long)page);
return -EINTR;
+ }
}
}
+ free_page((unsigned long)page);
return len - count;
}