Commit d3d03018 authored by Stelian Pop's avatar Stelian Pop Committed by Linus Torvalds

[PATCH] sonypi: replace homebrew queue with kfifo

Signed-off-by: default avatarStelian Pop <stelian@popies.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a7a17e02
...@@ -125,64 +125,6 @@ static int sonypi_ec_read(u8 addr, u8 *value) ...@@ -125,64 +125,6 @@ static int sonypi_ec_read(u8 addr, u8 *value)
return 0; return 0;
} }
/* Inits the queue */
static inline void sonypi_initq(void) {
sonypi_device.queue.head = sonypi_device.queue.tail = 0;
sonypi_device.queue.len = 0;
sonypi_device.queue.s_lock = SPIN_LOCK_UNLOCKED;
init_waitqueue_head(&sonypi_device.queue.proc_list);
}
/* Pulls an event from the queue */
static inline unsigned char sonypi_pullq(void) {
unsigned char result;
unsigned long flags;
spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
if (!sonypi_device.queue.len) {
spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
return 0;
}
result = sonypi_device.queue.buf[sonypi_device.queue.head];
sonypi_device.queue.head++;
sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
sonypi_device.queue.len--;
spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
return result;
}
/* Pushes an event into the queue */
static inline void sonypi_pushq(unsigned char event) {
unsigned long flags;
spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
if (sonypi_device.queue.len == SONYPI_BUF_SIZE) {
/* remove the first element */
sonypi_device.queue.head++;
sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
sonypi_device.queue.len--;
}
sonypi_device.queue.buf[sonypi_device.queue.tail] = event;
sonypi_device.queue.tail++;
sonypi_device.queue.tail &= (SONYPI_BUF_SIZE - 1);
sonypi_device.queue.len++;
kill_fasync(&sonypi_device.queue.fasync, SIGIO, POLL_IN);
wake_up_interruptible(&sonypi_device.queue.proc_list);
spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
}
/* Tests if the queue is empty */
static inline int sonypi_emptyq(void) {
int result;
unsigned long flags;
spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
result = (sonypi_device.queue.len == 0);
spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
return result;
}
static int ec_read16(u8 addr, u16 *value) { static int ec_read16(u8 addr, u16 *value) {
u8 val_lb, val_hb; u8 val_lb, val_hb;
if (sonypi_ec_read(addr, &val_lb)) if (sonypi_ec_read(addr, &val_lb))
...@@ -419,7 +361,11 @@ static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -419,7 +361,11 @@ static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
input_sync(jog_dev); input_sync(jog_dev);
} }
#endif /* SONYPI_USE_INPUT */ #endif /* SONYPI_USE_INPUT */
sonypi_pushq(event);
kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
wake_up_interruptible(&sonypi_device.fifo_proc_list);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -504,7 +450,7 @@ EXPORT_SYMBOL(sonypi_camera_command); ...@@ -504,7 +450,7 @@ EXPORT_SYMBOL(sonypi_camera_command);
static int sonypi_misc_fasync(int fd, struct file *filp, int on) { static int sonypi_misc_fasync(int fd, struct file *filp, int on) {
int retval; int retval;
retval = fasync_helper(fd, filp, on, &sonypi_device.queue.fasync); retval = fasync_helper(fd, filp, on, &sonypi_device.fifo_async);
if (retval < 0) if (retval < 0)
return retval; return retval;
return 0; return 0;
...@@ -522,7 +468,7 @@ static int sonypi_misc_open(struct inode * inode, struct file * file) { ...@@ -522,7 +468,7 @@ static int sonypi_misc_open(struct inode * inode, struct file * file) {
down(&sonypi_device.lock); down(&sonypi_device.lock);
/* Flush input queue on first open */ /* Flush input queue on first open */
if (!sonypi_device.open_count) if (!sonypi_device.open_count)
sonypi_initq(); kfifo_reset(sonypi_device.fifo);
sonypi_device.open_count++; sonypi_device.open_count++;
up(&sonypi_device.lock); up(&sonypi_device.lock);
return 0; return 0;
...@@ -531,40 +477,34 @@ static int sonypi_misc_open(struct inode * inode, struct file * file) { ...@@ -531,40 +477,34 @@ static int sonypi_misc_open(struct inode * inode, struct file * file) {
static ssize_t sonypi_misc_read(struct file * file, char __user * buf, static ssize_t sonypi_misc_read(struct file * file, char __user * buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
DECLARE_WAITQUEUE(wait, current); ssize_t ret;
ssize_t i = count;
unsigned char c; unsigned char c;
if (sonypi_emptyq()) { if ((kfifo_len(sonypi_device.fifo) == 0) &&
if (file->f_flags & O_NONBLOCK) (file->f_flags & O_NONBLOCK))
return -EAGAIN; return -EAGAIN;
add_wait_queue(&sonypi_device.queue.proc_list, &wait);
repeat: ret = wait_event_interruptible(sonypi_device.fifo_proc_list,
set_current_state(TASK_INTERRUPTIBLE); kfifo_len(sonypi_device.fifo) != 0);
if (sonypi_emptyq() && !signal_pending(current)) { if (ret)
schedule(); return ret;
goto repeat;
} while (ret < count &&
current->state = TASK_RUNNING; (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) {
remove_wait_queue(&sonypi_device.queue.proc_list, &wait); if (put_user(c, buf++))
} return -EFAULT;
while (i > 0 && !sonypi_emptyq()) { ret++;
c = sonypi_pullq();
put_user(c, buf++);
i--;
}
if (count - i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i;
} }
if (signal_pending(current))
return -ERESTARTSYS; if (ret > 0)
return 0; file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return ret;
} }
static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) { static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) {
poll_wait(file, &sonypi_device.queue.proc_list, wait); poll_wait(file, &sonypi_device.fifo_proc_list, wait);
if (!sonypi_emptyq()) if (kfifo_len(sonypi_device.fifo))
return POLLIN | POLLRDNORM; return POLLIN | POLLRDNORM;
return 0; return 0;
} }
...@@ -743,7 +683,16 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -743,7 +683,16 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
else else
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
sonypi_initq(); sonypi_device.fifo_lock = SPIN_LOCK_UNLOCKED;
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock);
if (IS_ERR(sonypi_device.fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
ret = PTR_ERR(sonypi_device.fifo);
goto out_fifo;
}
init_waitqueue_head(&sonypi_device.fifo_proc_list);
init_MUTEX(&sonypi_device.lock); init_MUTEX(&sonypi_device.lock);
sonypi_device.bluetooth_power = 0; sonypi_device.bluetooth_power = 0;
...@@ -896,6 +845,8 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -896,6 +845,8 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
out2: out2:
misc_deregister(&sonypi_misc_device); misc_deregister(&sonypi_misc_device);
out1: out1:
kfifo_free(sonypi_device.fifo);
out_fifo:
return ret; return ret;
} }
...@@ -929,6 +880,7 @@ static void __devexit sonypi_remove(void) { ...@@ -929,6 +880,7 @@ static void __devexit sonypi_remove(void) {
free_irq(sonypi_device.irq, sonypi_irq); free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size); release_region(sonypi_device.ioport1, sonypi_device.region_size);
misc_deregister(&sonypi_misc_device); misc_deregister(&sonypi_misc_device);
kfifo_free(sonypi_device.fifo);
printk(KERN_INFO "sonypi: removed.\n"); printk(KERN_INFO "sonypi: removed.\n");
} }
......
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include "linux/sonypi.h" #include <linux/kfifo.h>
#include <linux/sonypi.h>
/* type1 models use those */ /* type1 models use those */
#define SONYPI_IRQ_PORT 0x8034 #define SONYPI_IRQ_PORT 0x8034
...@@ -339,15 +340,6 @@ struct sonypi_eventtypes { ...@@ -339,15 +340,6 @@ struct sonypi_eventtypes {
}; };
#define SONYPI_BUF_SIZE 128 #define SONYPI_BUF_SIZE 128
struct sonypi_queue {
unsigned long head;
unsigned long tail;
unsigned long len;
spinlock_t s_lock;
wait_queue_head_t proc_list;
struct fasync_struct *fasync;
unsigned char buf[SONYPI_BUF_SIZE];
};
/* We enable input subsystem event forwarding if the input /* We enable input subsystem event forwarding if the input
* subsystem is compiled in, but only if sonypi is not into the * subsystem is compiled in, but only if sonypi is not into the
...@@ -372,7 +364,10 @@ struct sonypi_device { ...@@ -372,7 +364,10 @@ struct sonypi_device {
int camera_power; int camera_power;
int bluetooth_power; int bluetooth_power;
struct semaphore lock; struct semaphore lock;
struct sonypi_queue queue; struct kfifo *fifo;
spinlock_t fifo_lock;
wait_queue_head_t fifo_proc_list;
struct fasync_struct *fifo_async;
int open_count; int open_count;
int model; int model;
#ifdef SONYPI_USE_INPUT #ifdef SONYPI_USE_INPUT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment