aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c239
1 files changed, 149 insertions, 90 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index a2a742c8ff7e..1387c5f9c24d 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -58,6 +58,7 @@
58#include <linux/kfifo.h> 58#include <linux/kfifo.h>
59#include <linux/workqueue.h> 59#include <linux/workqueue.h>
60#include <linux/acpi.h> 60#include <linux/acpi.h>
61#include <linux/slab.h>
61#include <acpi/acpi_drivers.h> 62#include <acpi/acpi_drivers.h>
62#include <acpi/acpi_bus.h> 63#include <acpi/acpi_bus.h>
63#include <asm/uaccess.h> 64#include <asm/uaccess.h>
@@ -131,6 +132,7 @@ enum sony_nc_rfkill {
131 N_SONY_RFKILL, 132 N_SONY_RFKILL,
132}; 133};
133 134
135static int sony_rfkill_handle;
134static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; 136static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
135static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; 137static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
136static void sony_nc_rfkill_update(void); 138static void sony_nc_rfkill_update(void);
@@ -142,9 +144,9 @@ struct sony_laptop_input_s {
142 atomic_t users; 144 atomic_t users;
143 struct input_dev *jog_dev; 145 struct input_dev *jog_dev;
144 struct input_dev *key_dev; 146 struct input_dev *key_dev;
145 struct kfifo *fifo; 147 struct kfifo fifo;
146 spinlock_t fifo_lock; 148 spinlock_t fifo_lock;
147 struct workqueue_struct *wq; 149 struct timer_list release_key_timer;
148}; 150};
149 151
150static struct sony_laptop_input_s sony_laptop_input = { 152static struct sony_laptop_input_s sony_laptop_input = {
@@ -232,6 +234,7 @@ static int sony_laptop_input_index[] = {
232 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 234 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
233 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 235 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
234 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ 236 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
237 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */
235}; 238};
236 239
237static int sony_laptop_input_keycode_map[] = { 240static int sony_laptop_input_keycode_map[] = {
@@ -293,22 +296,30 @@ static int sony_laptop_input_keycode_map[] = {
293 KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ 296 KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
294 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ 297 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
295 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 298 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
299 KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */
296}; 300};
297 301
298/* release buttons after a short delay if pressed */ 302/* release buttons after a short delay if pressed */
299static void do_sony_laptop_release_key(struct work_struct *work) 303static void do_sony_laptop_release_key(unsigned long unused)
300{ 304{
301 struct sony_laptop_keypress kp; 305 struct sony_laptop_keypress kp;
306 unsigned long flags;
307
308 spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
302 309
303 while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, 310 if (kfifo_out(&sony_laptop_input.fifo,
304 sizeof(kp)) == sizeof(kp)) { 311 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
305 msleep(10);
306 input_report_key(kp.dev, kp.key, 0); 312 input_report_key(kp.dev, kp.key, 0);
307 input_sync(kp.dev); 313 input_sync(kp.dev);
308 } 314 }
315
316 /* If there is something in the fifo schedule next release. */
317 if (kfifo_len(&sony_laptop_input.fifo) != 0)
318 mod_timer(&sony_laptop_input.release_key_timer,
319 jiffies + msecs_to_jiffies(10));
320
321 spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
309} 322}
310static DECLARE_WORK(sony_laptop_release_key_work,
311 do_sony_laptop_release_key);
312 323
313/* forward event to the input subsystem */ 324/* forward event to the input subsystem */
314static void sony_laptop_report_input_event(u8 event) 325static void sony_laptop_report_input_event(u8 event)
@@ -362,12 +373,13 @@ static void sony_laptop_report_input_event(u8 event)
362 /* we emit the scancode so we can always remap the key */ 373 /* we emit the scancode so we can always remap the key */
363 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 374 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
364 input_sync(kp.dev); 375 input_sync(kp.dev);
365 kfifo_put(sony_laptop_input.fifo,
366 (unsigned char *)&kp, sizeof(kp));
367 376
368 if (!work_pending(&sony_laptop_release_key_work)) 377 /* schedule key release */
369 queue_work(sony_laptop_input.wq, 378 kfifo_in_locked(&sony_laptop_input.fifo,
370 &sony_laptop_release_key_work); 379 (unsigned char *)&kp, sizeof(kp),
380 &sony_laptop_input.fifo_lock);
381 mod_timer(&sony_laptop_input.release_key_timer,
382 jiffies + msecs_to_jiffies(10));
371 } else 383 } else
372 dprintk("unknown input event %.2x\n", event); 384 dprintk("unknown input event %.2x\n", event);
373} 385}
@@ -385,29 +397,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
385 397
386 /* kfifo */ 398 /* kfifo */
387 spin_lock_init(&sony_laptop_input.fifo_lock); 399 spin_lock_init(&sony_laptop_input.fifo_lock);
388 sony_laptop_input.fifo = 400 error = kfifo_alloc(&sony_laptop_input.fifo,
389 kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 401 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
390 &sony_laptop_input.fifo_lock); 402 if (error) {
391 if (IS_ERR(sony_laptop_input.fifo)) {
392 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 403 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
393 error = PTR_ERR(sony_laptop_input.fifo);
394 goto err_dec_users; 404 goto err_dec_users;
395 } 405 }
396 406
397 /* init workqueue */ 407 setup_timer(&sony_laptop_input.release_key_timer,
398 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); 408 do_sony_laptop_release_key, 0);
399 if (!sony_laptop_input.wq) {
400 printk(KERN_ERR DRV_PFX
401 "Unable to create workqueue.\n");
402 error = -ENXIO;
403 goto err_free_kfifo;
404 }
405 409
406 /* input keys */ 410 /* input keys */
407 key_dev = input_allocate_device(); 411 key_dev = input_allocate_device();
408 if (!key_dev) { 412 if (!key_dev) {
409 error = -ENOMEM; 413 error = -ENOMEM;
410 goto err_destroy_wq; 414 goto err_free_kfifo;
411 } 415 }
412 416
413 key_dev->name = "Sony Vaio Keys"; 417 key_dev->name = "Sony Vaio Keys";
@@ -416,18 +420,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
416 key_dev->dev.parent = &acpi_device->dev; 420 key_dev->dev.parent = &acpi_device->dev;
417 421
418 /* Initialize the Input Drivers: special keys */ 422 /* Initialize the Input Drivers: special keys */
419 set_bit(EV_KEY, key_dev->evbit); 423 input_set_capability(key_dev, EV_MSC, MSC_SCAN);
420 set_bit(EV_MSC, key_dev->evbit); 424
421 set_bit(MSC_SCAN, key_dev->mscbit); 425 __set_bit(EV_KEY, key_dev->evbit);
422 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 426 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
423 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 427 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
424 key_dev->keycode = &sony_laptop_input_keycode_map; 428 key_dev->keycode = &sony_laptop_input_keycode_map;
425 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { 429 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
426 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { 430 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
427 set_bit(sony_laptop_input_keycode_map[i], 431 __clear_bit(KEY_RESERVED, key_dev->keybit);
428 key_dev->keybit);
429 }
430 }
431 432
432 error = input_register_device(key_dev); 433 error = input_register_device(key_dev);
433 if (error) 434 if (error)
@@ -447,9 +448,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
447 jog_dev->id.vendor = PCI_VENDOR_ID_SONY; 448 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
448 key_dev->dev.parent = &acpi_device->dev; 449 key_dev->dev.parent = &acpi_device->dev;
449 450
450 jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 451 input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
451 jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); 452 input_set_capability(jog_dev, EV_REL, REL_WHEEL);
452 jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
453 453
454 error = input_register_device(jog_dev); 454 error = input_register_device(jog_dev);
455 if (error) 455 if (error)
@@ -470,11 +470,8 @@ err_unregister_keydev:
470err_free_keydev: 470err_free_keydev:
471 input_free_device(key_dev); 471 input_free_device(key_dev);
472 472
473err_destroy_wq:
474 destroy_workqueue(sony_laptop_input.wq);
475
476err_free_kfifo: 473err_free_kfifo:
477 kfifo_free(sony_laptop_input.fifo); 474 kfifo_free(&sony_laptop_input.fifo);
478 475
479err_dec_users: 476err_dec_users:
480 atomic_dec(&sony_laptop_input.users); 477 atomic_dec(&sony_laptop_input.users);
@@ -483,12 +480,23 @@ err_dec_users:
483 480
484static void sony_laptop_remove_input(void) 481static void sony_laptop_remove_input(void)
485{ 482{
486 /* cleanup only after the last user has gone */ 483 struct sony_laptop_keypress kp = { NULL };
484
485 /* Cleanup only after the last user has gone */
487 if (!atomic_dec_and_test(&sony_laptop_input.users)) 486 if (!atomic_dec_and_test(&sony_laptop_input.users))
488 return; 487 return;
489 488
490 /* flush workqueue first */ 489 del_timer_sync(&sony_laptop_input.release_key_timer);
491 flush_workqueue(sony_laptop_input.wq); 490
491 /*
492 * Generate key-up events for remaining keys. Note that we don't
493 * need locking since nobody is adding new events to the kfifo.
494 */
495 while (kfifo_out(&sony_laptop_input.fifo,
496 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
497 input_report_key(kp.dev, kp.key, 0);
498 input_sync(kp.dev);
499 }
492 500
493 /* destroy input devs */ 501 /* destroy input devs */
494 input_unregister_device(sony_laptop_input.key_dev); 502 input_unregister_device(sony_laptop_input.key_dev);
@@ -499,8 +507,7 @@ static void sony_laptop_remove_input(void)
499 sony_laptop_input.jog_dev = NULL; 507 sony_laptop_input.jog_dev = NULL;
500 } 508 }
501 509
502 destroy_workqueue(sony_laptop_input.wq); 510 kfifo_free(&sony_laptop_input.fifo);
503 kfifo_free(sony_laptop_input.fifo);
504} 511}
505 512
506/*********** Platform Device ***********/ 513/*********** Platform Device ***********/
@@ -890,6 +897,8 @@ static struct sony_nc_event sony_100_events[] = {
890 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 897 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
891 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, 898 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
892 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, 899 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
900 { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
901 { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
893 { 0, 0 }, 902 { 0, 0 },
894}; 903};
895 904
@@ -961,7 +970,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
961 else 970 else
962 sony_laptop_report_input_event(ev); 971 sony_laptop_report_input_event(ev);
963 } 972 }
964 } else if (sony_find_snc_handle(0x124) == ev) { 973 } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
965 sony_nc_rfkill_update(); 974 sony_nc_rfkill_update();
966 return; 975 return;
967 } 976 }
@@ -1067,7 +1076,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked)
1067 if (!blocked) 1076 if (!blocked)
1068 argument |= 0xff0000; 1077 argument |= 0xff0000;
1069 1078
1070 return sony_call_snc_handle(0x124, argument, &result); 1079 return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1071} 1080}
1072 1081
1073static const struct rfkill_ops sony_rfkill_ops = { 1082static const struct rfkill_ops sony_rfkill_ops = {
@@ -1110,7 +1119,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
1110 if (!rfk) 1119 if (!rfk)
1111 return -ENOMEM; 1120 return -ENOMEM;
1112 1121
1113 sony_call_snc_handle(0x124, 0x200, &result); 1122 sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1114 hwblock = !(result & 0x1); 1123 hwblock = !(result & 0x1);
1115 rfkill_set_hw_state(rfk, hwblock); 1124 rfkill_set_hw_state(rfk, hwblock);
1116 1125
@@ -1129,7 +1138,7 @@ static void sony_nc_rfkill_update()
1129 int result; 1138 int result;
1130 bool hwblock; 1139 bool hwblock;
1131 1140
1132 sony_call_snc_handle(0x124, 0x200, &result); 1141 sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1133 hwblock = !(result & 0x1); 1142 hwblock = !(result & 0x1);
1134 1143
1135 for (i = 0; i < N_SONY_RFKILL; i++) { 1144 for (i = 0; i < N_SONY_RFKILL; i++) {
@@ -1145,36 +1154,82 @@ static void sony_nc_rfkill_update()
1145 continue; 1154 continue;
1146 } 1155 }
1147 1156
1148 sony_call_snc_handle(0x124, argument, &result); 1157 sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1149 rfkill_set_states(sony_rfkill_devices[i], 1158 rfkill_set_states(sony_rfkill_devices[i],
1150 !(result & 0xf), false); 1159 !(result & 0xf), false);
1151 } 1160 }
1152} 1161}
1153 1162
1154static int sony_nc_rfkill_setup(struct acpi_device *device) 1163static void sony_nc_rfkill_setup(struct acpi_device *device)
1155{ 1164{
1156 int result, ret; 1165 int offset;
1166 u8 dev_code, i;
1167 acpi_status status;
1168 struct acpi_object_list params;
1169 union acpi_object in_obj;
1170 union acpi_object *device_enum;
1171 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1157 1172
1158 if (sony_find_snc_handle(0x124) == -1) 1173 offset = sony_find_snc_handle(0x124);
1159 return -1; 1174 if (offset == -1) {
1175 offset = sony_find_snc_handle(0x135);
1176 if (offset == -1)
1177 return;
1178 else
1179 sony_rfkill_handle = 0x135;
1180 } else
1181 sony_rfkill_handle = 0x124;
1182 dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
1160 1183
1161 ret = sony_call_snc_handle(0x124, 0xb00, &result); 1184 /* need to read the whole buffer returned by the acpi call to SN06
1162 if (ret) { 1185 * here otherwise we may miss some features
1163 printk(KERN_INFO DRV_PFX 1186 */
1164 "Unable to enumerate rfkill devices: %x\n", ret); 1187 params.count = 1;
1165 return ret; 1188 params.pointer = &in_obj;
1189 in_obj.type = ACPI_TYPE_INTEGER;
1190 in_obj.integer.value = offset;
1191 status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1192 &buffer);
1193 if (ACPI_FAILURE(status)) {
1194 dprintk("Radio device enumeration failed\n");
1195 return;
1196 }
1197
1198 device_enum = (union acpi_object *) buffer.pointer;
1199 if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) {
1200 printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n",
1201 device_enum->type);
1202 goto out_no_enum;
1166 } 1203 }
1167 1204
1168 if (result & 0x1) 1205 /* the buffer is filled with magic numbers describing the devices
1169 sony_nc_setup_rfkill(device, SONY_WIFI); 1206 * available, 0xff terminates the enumeration
1170 if (result & 0x2) 1207 */
1171 sony_nc_setup_rfkill(device, SONY_BLUETOOTH); 1208 for (i = 0; i < device_enum->buffer.length; i++) {
1172 if (result & 0x1c)
1173 sony_nc_setup_rfkill(device, SONY_WWAN);
1174 if (result & 0x20)
1175 sony_nc_setup_rfkill(device, SONY_WIMAX);
1176 1209
1177 return 0; 1210 dev_code = *(device_enum->buffer.pointer + i);
1211 if (dev_code == 0xff)
1212 break;
1213
1214 dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
1215
1216 if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
1217 sony_nc_setup_rfkill(device, SONY_WIFI);
1218
1219 if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1220 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1221
1222 if ((0xf0 & dev_code) == 0x20 &&
1223 !sony_rfkill_devices[SONY_WWAN])
1224 sony_nc_setup_rfkill(device, SONY_WWAN);
1225
1226 if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1227 sony_nc_setup_rfkill(device, SONY_WIMAX);
1228 }
1229
1230out_no_enum:
1231 kfree(buffer.pointer);
1232 return;
1178} 1233}
1179 1234
1180static int sony_nc_add(struct acpi_device *device) 1235static int sony_nc_add(struct acpi_device *device)
@@ -1203,7 +1258,7 @@ static int sony_nc_add(struct acpi_device *device)
1203 1258
1204 if (debug) { 1259 if (debug) {
1205 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1260 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
1206 1, sony_walk_callback, NULL, NULL); 1261 1, sony_walk_callback, NULL, NULL, NULL);
1207 if (ACPI_FAILURE(status)) { 1262 if (ACPI_FAILURE(status)) {
1208 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); 1263 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
1209 result = -ENODEV; 1264 result = -ENODEV;
@@ -1237,9 +1292,13 @@ static int sony_nc_add(struct acpi_device *device)
1237 "controlled by ACPI video driver\n"); 1292 "controlled by ACPI video driver\n");
1238 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", 1293 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
1239 &handle))) { 1294 &handle))) {
1295 struct backlight_properties props;
1296 memset(&props, 0, sizeof(struct backlight_properties));
1297 props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
1240 sony_backlight_device = backlight_device_register("sony", NULL, 1298 sony_backlight_device = backlight_device_register("sony", NULL,
1241 NULL, 1299 NULL,
1242 &sony_backlight_ops); 1300 &sony_backlight_ops,
1301 &props);
1243 1302
1244 if (IS_ERR(sony_backlight_device)) { 1303 if (IS_ERR(sony_backlight_device)) {
1245 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); 1304 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
@@ -1248,8 +1307,6 @@ static int sony_nc_add(struct acpi_device *device)
1248 sony_backlight_device->props.brightness = 1307 sony_backlight_device->props.brightness =
1249 sony_backlight_get_brightness 1308 sony_backlight_get_brightness
1250 (sony_backlight_device); 1309 (sony_backlight_device);
1251 sony_backlight_device->props.max_brightness =
1252 SONY_MAX_BRIGHTNESS - 1;
1253 } 1310 }
1254 1311
1255 } 1312 }
@@ -2079,7 +2136,7 @@ static struct attribute_group spic_attribute_group = {
2079 2136
2080struct sonypi_compat_s { 2137struct sonypi_compat_s {
2081 struct fasync_struct *fifo_async; 2138 struct fasync_struct *fifo_async;
2082 struct kfifo *fifo; 2139 struct kfifo fifo;
2083 spinlock_t fifo_lock; 2140 spinlock_t fifo_lock;
2084 wait_queue_head_t fifo_proc_list; 2141 wait_queue_head_t fifo_proc_list;
2085 atomic_t open_count; 2142 atomic_t open_count;
@@ -2104,12 +2161,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file)
2104 /* Flush input queue on first open */ 2161 /* Flush input queue on first open */
2105 unsigned long flags; 2162 unsigned long flags;
2106 2163
2107 spin_lock_irqsave(sonypi_compat.fifo->lock, flags); 2164 spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
2108 2165
2109 if (atomic_inc_return(&sonypi_compat.open_count) == 1) 2166 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
2110 __kfifo_reset(sonypi_compat.fifo); 2167 kfifo_reset(&sonypi_compat.fifo);
2111 2168
2112 spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); 2169 spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
2113 2170
2114 return 0; 2171 return 0;
2115} 2172}
@@ -2120,17 +2177,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
2120 ssize_t ret; 2177 ssize_t ret;
2121 unsigned char c; 2178 unsigned char c;
2122 2179
2123 if ((kfifo_len(sonypi_compat.fifo) == 0) && 2180 if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
2124 (file->f_flags & O_NONBLOCK)) 2181 (file->f_flags & O_NONBLOCK))
2125 return -EAGAIN; 2182 return -EAGAIN;
2126 2183
2127 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, 2184 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
2128 kfifo_len(sonypi_compat.fifo) != 0); 2185 kfifo_len(&sonypi_compat.fifo) != 0);
2129 if (ret) 2186 if (ret)
2130 return ret; 2187 return ret;
2131 2188
2132 while (ret < count && 2189 while (ret < count &&
2133 (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { 2190 (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
2191 &sonypi_compat.fifo_lock) == sizeof(c))) {
2134 if (put_user(c, buf++)) 2192 if (put_user(c, buf++))
2135 return -EFAULT; 2193 return -EFAULT;
2136 ret++; 2194 ret++;
@@ -2147,7 +2205,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) 2205static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
2148{ 2206{
2149 poll_wait(file, &sonypi_compat.fifo_proc_list, wait); 2207 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
2150 if (kfifo_len(sonypi_compat.fifo)) 2208 if (kfifo_len(&sonypi_compat.fifo))
2151 return POLLIN | POLLRDNORM; 2209 return POLLIN | POLLRDNORM;
2152 return 0; 2210 return 0;
2153} 2211}
@@ -2309,7 +2367,8 @@ static struct miscdevice sonypi_misc_device = {
2309 2367
2310static void sonypi_compat_report_event(u8 event) 2368static void sonypi_compat_report_event(u8 event)
2311{ 2369{
2312 kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); 2370 kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
2371 sizeof(event), &sonypi_compat.fifo_lock);
2313 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); 2372 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
2314 wake_up_interruptible(&sonypi_compat.fifo_proc_list); 2373 wake_up_interruptible(&sonypi_compat.fifo_proc_list);
2315} 2374}
@@ -2319,11 +2378,11 @@ static int sonypi_compat_init(void)
2319 int error; 2378 int error;
2320 2379
2321 spin_lock_init(&sonypi_compat.fifo_lock); 2380 spin_lock_init(&sonypi_compat.fifo_lock);
2322 sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 2381 error =
2323 &sonypi_compat.fifo_lock); 2382 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
2324 if (IS_ERR(sonypi_compat.fifo)) { 2383 if (error) {
2325 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 2384 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
2326 return PTR_ERR(sonypi_compat.fifo); 2385 return error;
2327 } 2386 }
2328 2387
2329 init_waitqueue_head(&sonypi_compat.fifo_proc_list); 2388 init_waitqueue_head(&sonypi_compat.fifo_proc_list);
@@ -2342,14 +2401,14 @@ static int sonypi_compat_init(void)
2342 return 0; 2401 return 0;
2343 2402
2344err_free_kfifo: 2403err_free_kfifo:
2345 kfifo_free(sonypi_compat.fifo); 2404 kfifo_free(&sonypi_compat.fifo);
2346 return error; 2405 return error;
2347} 2406}
2348 2407
2349static void sonypi_compat_exit(void) 2408static void sonypi_compat_exit(void)
2350{ 2409{
2351 misc_deregister(&sonypi_misc_device); 2410 misc_deregister(&sonypi_misc_device);
2352 kfifo_free(sonypi_compat.fifo); 2411 kfifo_free(&sonypi_compat.fifo);
2353} 2412}
2354#else 2413#else
2355static int sonypi_compat_init(void) { return 0; } 2414static int sonypi_compat_init(void) { return 0; }