aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
authorStefani Seibold <stefani@seibold.net>2009-12-21 17:37:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-22 17:17:55 -0500
commit45465487897a1c6d508b14b904dc5777f7ec7e04 (patch)
tree935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/platform/x86/sony-laptop.c
parent2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (diff)
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation. The current kernel fifo API is not very widely used, because it has to many constrains. Only 17 files in the current 2.6.31-rc5 used it. FIFO's are like list's a very basic thing and a kfifo API which handles the most use case would save a lot of development time and memory resources. I think this are the reasons why kfifo is not in use: - The API is to simple, important functions are missing - A fifo can be only allocated dynamically - There is a requirement of a spinlock whether you need it or not - There is no support for data records inside a fifo So I decided to extend the kfifo in a more generic way without blowing up the API to much. The new API has the following benefits: - Generic usage: For kernel internal use and/or device driver. - Provide an API for the most use case. - Slim API: The whole API provides 25 functions. - Linux style habit. - DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros - Direct copy_to_user from the fifo and copy_from_user into the fifo. - The kfifo itself is an in place member of the using data structure, this save an indirection access and does not waste the kernel allocator. - Lockless access: if only one reader and one writer is active on the fifo, which is the common use case, no additional locking is necessary. - Remove spinlock - give the user the freedom of choice what kind of locking to use if one is required. - Ability to handle records. Three type of records are supported: - Variable length records between 0-255 bytes, with a record size field of 1 bytes. - Variable length records between 0-65535 bytes, with a record size field of 2 bytes. - Fixed size records, which no record size field. - Preserve memory resource. - Performance! - Easy to use! This patch: Since most users want to have the kfifo as part of another object, reorganize the code to allow including struct kfifo in another data structure. This requires changing the kfifo_alloc and kfifo_init prototypes so that we pass an existing kfifo pointer into them. This patch changes the implementation and all existing users. [akpm@linux-foundation.org: fix warning] Signed-off-by: Stefani Seibold <stefani@seibold.net> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com> Acked-by: Andi Kleen <ak@linux.intel.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 7a2cc8a5c975..04625a048e74 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -142,7 +142,7 @@ struct sony_laptop_input_s {
142 atomic_t users; 142 atomic_t users;
143 struct input_dev *jog_dev; 143 struct input_dev *jog_dev;
144 struct input_dev *key_dev; 144 struct input_dev *key_dev;
145 struct kfifo *fifo; 145 struct kfifo fifo;
146 spinlock_t fifo_lock; 146 spinlock_t fifo_lock;
147 struct workqueue_struct *wq; 147 struct workqueue_struct *wq;
148}; 148};
@@ -300,7 +300,7 @@ static void do_sony_laptop_release_key(struct work_struct *work)
300{ 300{
301 struct sony_laptop_keypress kp; 301 struct sony_laptop_keypress kp;
302 302
303 while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, 303 while (kfifo_get(&sony_laptop_input.fifo, (unsigned char *)&kp,
304 sizeof(kp)) == sizeof(kp)) { 304 sizeof(kp)) == sizeof(kp)) {
305 msleep(10); 305 msleep(10);
306 input_report_key(kp.dev, kp.key, 0); 306 input_report_key(kp.dev, kp.key, 0);
@@ -362,7 +362,7 @@ static void sony_laptop_report_input_event(u8 event)
362 /* we emit the scancode so we can always remap the key */ 362 /* we emit the scancode so we can always remap the key */
363 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 363 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
364 input_sync(kp.dev); 364 input_sync(kp.dev);
365 kfifo_put(sony_laptop_input.fifo, 365 kfifo_put(&sony_laptop_input.fifo,
366 (unsigned char *)&kp, sizeof(kp)); 366 (unsigned char *)&kp, sizeof(kp));
367 367
368 if (!work_pending(&sony_laptop_release_key_work)) 368 if (!work_pending(&sony_laptop_release_key_work))
@@ -385,12 +385,11 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
385 385
386 /* kfifo */ 386 /* kfifo */
387 spin_lock_init(&sony_laptop_input.fifo_lock); 387 spin_lock_init(&sony_laptop_input.fifo_lock);
388 sony_laptop_input.fifo = 388 error =
389 kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 389 kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
390 &sony_laptop_input.fifo_lock); 390 &sony_laptop_input.fifo_lock);
391 if (IS_ERR(sony_laptop_input.fifo)) { 391 if (error) {
392 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 392 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
393 error = PTR_ERR(sony_laptop_input.fifo);
394 goto err_dec_users; 393 goto err_dec_users;
395 } 394 }
396 395
@@ -474,7 +473,7 @@ err_destroy_wq:
474 destroy_workqueue(sony_laptop_input.wq); 473 destroy_workqueue(sony_laptop_input.wq);
475 474
476err_free_kfifo: 475err_free_kfifo:
477 kfifo_free(sony_laptop_input.fifo); 476 kfifo_free(&sony_laptop_input.fifo);
478 477
479err_dec_users: 478err_dec_users:
480 atomic_dec(&sony_laptop_input.users); 479 atomic_dec(&sony_laptop_input.users);
@@ -500,7 +499,7 @@ static void sony_laptop_remove_input(void)
500 } 499 }
501 500
502 destroy_workqueue(sony_laptop_input.wq); 501 destroy_workqueue(sony_laptop_input.wq);
503 kfifo_free(sony_laptop_input.fifo); 502 kfifo_free(&sony_laptop_input.fifo);
504} 503}
505 504
506/*********** Platform Device ***********/ 505/*********** Platform Device ***********/
@@ -2079,7 +2078,7 @@ static struct attribute_group spic_attribute_group = {
2079 2078
2080struct sonypi_compat_s { 2079struct sonypi_compat_s {
2081 struct fasync_struct *fifo_async; 2080 struct fasync_struct *fifo_async;
2082 struct kfifo *fifo; 2081 struct kfifo fifo;
2083 spinlock_t fifo_lock; 2082 spinlock_t fifo_lock;
2084 wait_queue_head_t fifo_proc_list; 2083 wait_queue_head_t fifo_proc_list;
2085 atomic_t open_count; 2084 atomic_t open_count;
@@ -2104,12 +2103,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file)
2104 /* Flush input queue on first open */ 2103 /* Flush input queue on first open */
2105 unsigned long flags; 2104 unsigned long flags;
2106 2105
2107 spin_lock_irqsave(sonypi_compat.fifo->lock, flags); 2106 spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
2108 2107
2109 if (atomic_inc_return(&sonypi_compat.open_count) == 1) 2108 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
2110 __kfifo_reset(sonypi_compat.fifo); 2109 __kfifo_reset(&sonypi_compat.fifo);
2111 2110
2112 spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); 2111 spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
2113 2112
2114 return 0; 2113 return 0;
2115} 2114}
@@ -2120,17 +2119,17 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
2120 ssize_t ret; 2119 ssize_t ret;
2121 unsigned char c; 2120 unsigned char c;
2122 2121
2123 if ((kfifo_len(sonypi_compat.fifo) == 0) && 2122 if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
2124 (file->f_flags & O_NONBLOCK)) 2123 (file->f_flags & O_NONBLOCK))
2125 return -EAGAIN; 2124 return -EAGAIN;
2126 2125
2127 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, 2126 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
2128 kfifo_len(sonypi_compat.fifo) != 0); 2127 kfifo_len(&sonypi_compat.fifo) != 0);
2129 if (ret) 2128 if (ret)
2130 return ret; 2129 return ret;
2131 2130
2132 while (ret < count && 2131 while (ret < count &&
2133 (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { 2132 (kfifo_get(&sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
2134 if (put_user(c, buf++)) 2133 if (put_user(c, buf++))
2135 return -EFAULT; 2134 return -EFAULT;
2136 ret++; 2135 ret++;
@@ -2147,7 +2146,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
2147static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) 2146static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
2148{ 2147{
2149 poll_wait(file, &sonypi_compat.fifo_proc_list, wait); 2148 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
2150 if (kfifo_len(sonypi_compat.fifo)) 2149 if (kfifo_len(&sonypi_compat.fifo))
2151 return POLLIN | POLLRDNORM; 2150 return POLLIN | POLLRDNORM;
2152 return 0; 2151 return 0;
2153} 2152}
@@ -2309,7 +2308,7 @@ static struct miscdevice sonypi_misc_device = {
2309 2308
2310static void sonypi_compat_report_event(u8 event) 2309static void sonypi_compat_report_event(u8 event)
2311{ 2310{
2312 kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); 2311 kfifo_put(&sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
2313 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); 2312 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
2314 wake_up_interruptible(&sonypi_compat.fifo_proc_list); 2313 wake_up_interruptible(&sonypi_compat.fifo_proc_list);
2315} 2314}
@@ -2319,11 +2318,12 @@ static int sonypi_compat_init(void)
2319 int error; 2318 int error;
2320 2319
2321 spin_lock_init(&sonypi_compat.fifo_lock); 2320 spin_lock_init(&sonypi_compat.fifo_lock);
2322 sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 2321 error =
2322 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
2323 &sonypi_compat.fifo_lock); 2323 &sonypi_compat.fifo_lock);
2324 if (IS_ERR(sonypi_compat.fifo)) { 2324 if (error) {
2325 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 2325 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
2326 return PTR_ERR(sonypi_compat.fifo); 2326 return error;
2327 } 2327 }
2328 2328
2329 init_waitqueue_head(&sonypi_compat.fifo_proc_list); 2329 init_waitqueue_head(&sonypi_compat.fifo_proc_list);
@@ -2342,14 +2342,14 @@ static int sonypi_compat_init(void)
2342 return 0; 2342 return 0;
2343 2343
2344err_free_kfifo: 2344err_free_kfifo:
2345 kfifo_free(sonypi_compat.fifo); 2345 kfifo_free(&sonypi_compat.fifo);
2346 return error; 2346 return error;
2347} 2347}
2348 2348
2349static void sonypi_compat_exit(void) 2349static void sonypi_compat_exit(void)
2350{ 2350{
2351 misc_deregister(&sonypi_misc_device); 2351 misc_deregister(&sonypi_misc_device);
2352 kfifo_free(sonypi_compat.fifo); 2352 kfifo_free(&sonypi_compat.fifo);
2353} 2353}
2354#else 2354#else
2355static int sonypi_compat_init(void) { return 0; } 2355static int sonypi_compat_init(void) { return 0; }