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.c279
1 files changed, 154 insertions, 125 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index afdbdaaf80cb..5af53340da6f 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -131,6 +131,7 @@ enum sony_nc_rfkill {
N_SONY_RFKILL,
};
+static int sony_rfkill_handle;
static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
static void sony_nc_rfkill_update(void);
@@ -142,7 +143,7 @@ struct sony_laptop_input_s {
atomic_t users;
struct input_dev *jog_dev;
struct input_dev *key_dev;
- struct kfifo *fifo;
+ struct kfifo fifo;
spinlock_t fifo_lock;
struct workqueue_struct *wq;
};
@@ -232,6 +233,7 @@ static int sony_laptop_input_index[] = {
56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
-1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
+ 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */
};
static int sony_laptop_input_keycode_map[] = {
@@ -293,6 +295,7 @@ static int sony_laptop_input_keycode_map[] = {
KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
+ KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */
};
/* release buttons after a short delay if pressed */
@@ -300,8 +303,9 @@ static void do_sony_laptop_release_key(struct work_struct *work)
{
struct sony_laptop_keypress kp;
- while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp,
- sizeof(kp)) == sizeof(kp)) {
+ while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp,
+ sizeof(kp), &sony_laptop_input.fifo_lock)
+ == sizeof(kp)) {
msleep(10);
input_report_key(kp.dev, kp.key, 0);
input_sync(kp.dev);
@@ -362,8 +366,9 @@ static void sony_laptop_report_input_event(u8 event)
/* we emit the scancode so we can always remap the key */
input_event(kp.dev, EV_MSC, MSC_SCAN, event);
input_sync(kp.dev);
- kfifo_put(sony_laptop_input.fifo,
- (unsigned char *)&kp, sizeof(kp));
+ kfifo_in_locked(&sony_laptop_input.fifo,
+ (unsigned char *)&kp, sizeof(kp),
+ &sony_laptop_input.fifo_lock);
if (!work_pending(&sony_laptop_release_key_work))
queue_work(sony_laptop_input.wq,
@@ -385,12 +390,10 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
/* kfifo */
spin_lock_init(&sony_laptop_input.fifo_lock);
- sony_laptop_input.fifo =
- kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
- &sony_laptop_input.fifo_lock);
- if (IS_ERR(sony_laptop_input.fifo)) {
+ error =
+ kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+ if (error) {
printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
- error = PTR_ERR(sony_laptop_input.fifo);
goto err_dec_users;
}
@@ -474,7 +477,7 @@ err_destroy_wq:
destroy_workqueue(sony_laptop_input.wq);
err_free_kfifo:
- kfifo_free(sony_laptop_input.fifo);
+ kfifo_free(&sony_laptop_input.fifo);
err_dec_users:
atomic_dec(&sony_laptop_input.users);
@@ -500,7 +503,7 @@ static void sony_laptop_remove_input(void)
}
destroy_workqueue(sony_laptop_input.wq);
- kfifo_free(sony_laptop_input.fifo);
+ kfifo_free(&sony_laptop_input.fifo);
}
/*********** Platform Device ***********/
@@ -890,6 +893,8 @@ static struct sony_nc_event sony_100_events[] = {
{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
{ 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
+ { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
+ { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0, 0 },
};
@@ -961,7 +966,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
else
sony_laptop_report_input_event(ev);
}
- } else if (sony_find_snc_handle(0x124) == ev) {
+ } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
sony_nc_rfkill_update();
return;
}
@@ -1067,7 +1072,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked)
if (!blocked)
argument |= 0xff0000;
- return sony_call_snc_handle(0x124, argument, &result);
+ return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
}
static const struct rfkill_ops sony_rfkill_ops = {
@@ -1110,7 +1115,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
if (!rfk)
return -ENOMEM;
- sony_call_snc_handle(0x124, 0x200, &result);
+ sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
hwblock = !(result & 0x1);
rfkill_set_hw_state(rfk, hwblock);
@@ -1129,7 +1134,7 @@ static void sony_nc_rfkill_update()
int result;
bool hwblock;
- sony_call_snc_handle(0x124, 0x200, &result);
+ sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
hwblock = !(result & 0x1);
for (i = 0; i < N_SONY_RFKILL; i++) {
@@ -1145,36 +1150,79 @@ static void sony_nc_rfkill_update()
continue;
}
- sony_call_snc_handle(0x124, argument, &result);
+ sony_call_snc_handle(sony_rfkill_handle, argument, &result);
rfkill_set_states(sony_rfkill_devices[i],
!(result & 0xf), false);
}
}
-static int sony_nc_rfkill_setup(struct acpi_device *device)
+static void sony_nc_rfkill_setup(struct acpi_device *device)
{
- int result, ret;
+ int offset;
+ u8 dev_code, i;
+ acpi_status status;
+ struct acpi_object_list params;
+ union acpi_object in_obj;
+ union acpi_object *device_enum;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- if (sony_find_snc_handle(0x124) == -1)
- return -1;
+ offset = sony_find_snc_handle(0x124);
+ if (offset == -1) {
+ offset = sony_find_snc_handle(0x135);
+ if (offset == -1)
+ return;
+ else
+ sony_rfkill_handle = 0x135;
+ } else
+ sony_rfkill_handle = 0x124;
+ dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
- ret = sony_call_snc_handle(0x124, 0xb00, &result);
- if (ret) {
- printk(KERN_INFO DRV_PFX
- "Unable to enumerate rfkill devices: %x\n", ret);
- return ret;
+ /* need to read the whole buffer returned by the acpi call to SN06
+ * here otherwise we may miss some features
+ */
+ params.count = 1;
+ params.pointer = &in_obj;
+ in_obj.type = ACPI_TYPE_INTEGER;
+ in_obj.integer.value = offset;
+ status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
+ &buffer);
+ if (ACPI_FAILURE(status)) {
+ dprintk("Radio device enumeration failed\n");
+ return;
+ }
+
+ device_enum = (union acpi_object *) buffer.pointer;
+ if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) {
+ printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n",
+ device_enum->type);
+ goto out_no_enum;
}
- if (result & 0x1)
- sony_nc_setup_rfkill(device, SONY_WIFI);
- if (result & 0x2)
- sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
- if (result & 0x1c)
- sony_nc_setup_rfkill(device, SONY_WWAN);
- if (result & 0x20)
- sony_nc_setup_rfkill(device, SONY_WIMAX);
+ /* the buffer is filled with magic numbers describing the devices
+ * available, 0xff terminates the enumeration
+ */
+ while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff &&
+ i < device_enum->buffer.length) {
+ i++;
+ dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
- return 0;
+ if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
+ sony_nc_setup_rfkill(device, SONY_WIFI);
+
+ if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
+ sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
+
+ if ((0xf0 & dev_code) == 0x20 &&
+ !sony_rfkill_devices[SONY_WWAN])
+ sony_nc_setup_rfkill(device, SONY_WWAN);
+
+ if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
+ sony_nc_setup_rfkill(device, SONY_WIMAX);
+ }
+
+out_no_enum:
+ kfree(buffer.pointer);
+ return;
}
static int sony_nc_add(struct acpi_device *device)
@@ -1203,7 +1251,7 @@ static int sony_nc_add(struct acpi_device *device)
if (debug) {
status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
- 1, sony_walk_callback, NULL, NULL);
+ 1, sony_walk_callback, NULL, NULL, NULL);
if (ACPI_FAILURE(status)) {
printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
result = -ENODEV;
@@ -1211,15 +1259,6 @@ static int sony_nc_add(struct acpi_device *device)
}
}
- /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1
- * should be respected as we already checked for the device presence above */
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) {
- dprintk("Invoking _INI\n");
- if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI,
- NULL, NULL)))
- dprintk("_INI Method failed\n");
- }
-
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
&handle))) {
if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
@@ -1399,27 +1438,20 @@ struct sonypi_eventtypes {
struct sonypi_event *events;
};
-struct device_ctrl {
+struct sony_pic_dev {
+ struct acpi_device *acpi_dev;
+ struct sony_pic_irq *cur_irq;
+ struct sony_pic_ioport *cur_ioport;
+ struct list_head interrupts;
+ struct list_head ioports;
+ struct mutex lock;
+ struct sonypi_eventtypes *event_types;
+ int (*handle_irq)(const u8, const u8);
int model;
- int (*handle_irq)(const u8, const u8);
u16 evport_offset;
- u8 has_camera;
- u8 has_bluetooth;
- u8 has_wwan;
- struct sonypi_eventtypes *event_types;
-};
-
-struct sony_pic_dev {
- struct device_ctrl *control;
- struct acpi_device *acpi_dev;
- struct sony_pic_irq *cur_irq;
- struct sony_pic_ioport *cur_ioport;
- struct list_head interrupts;
- struct list_head ioports;
- struct mutex lock;
- u8 camera_power;
- u8 bluetooth_power;
- u8 wwan_power;
+ u8 camera_power;
+ u8 bluetooth_power;
+ u8 wwan_power;
};
static struct sony_pic_dev spic_dev = {
@@ -1427,6 +1459,8 @@ static struct sony_pic_dev spic_dev = {
.ioports = LIST_HEAD_INIT(spic_dev.ioports),
};
+static int spic_drv_registered;
+
/* Event masks */
#define SONYPI_JOGGER_MASK 0x00000001
#define SONYPI_CAPTURE_MASK 0x00000002
@@ -1724,27 +1758,6 @@ static int type3_handle_irq(const u8 data_mask, const u8 ev)
return 1;
}
-static struct device_ctrl spic_types[] = {
- {
- .model = SONYPI_DEVICE_TYPE1,
- .handle_irq = NULL,
- .evport_offset = SONYPI_TYPE1_OFFSET,
- .event_types = type1_events,
- },
- {
- .model = SONYPI_DEVICE_TYPE2,
- .handle_irq = NULL,
- .evport_offset = SONYPI_TYPE2_OFFSET,
- .event_types = type2_events,
- },
- {
- .model = SONYPI_DEVICE_TYPE3,
- .handle_irq = type3_handle_irq,
- .evport_offset = SONYPI_TYPE3_OFFSET,
- .event_types = type3_events,
- },
-};
-
static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
{
struct pci_dev *pcidev;
@@ -1752,48 +1765,63 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
if (pcidev) {
- dev->control = &spic_types[0];
+ dev->model = SONYPI_DEVICE_TYPE1;
+ dev->evport_offset = SONYPI_TYPE1_OFFSET;
+ dev->event_types = type1_events;
goto out;
}
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
if (pcidev) {
- dev->control = &spic_types[2];
+ dev->model = SONYPI_DEVICE_TYPE2;
+ dev->evport_offset = SONYPI_TYPE2_OFFSET;
+ dev->event_types = type2_events;
goto out;
}
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
if (pcidev) {
- dev->control = &spic_types[2];
+ dev->model = SONYPI_DEVICE_TYPE3;
+ dev->handle_irq = type3_handle_irq;
+ dev->evport_offset = SONYPI_TYPE3_OFFSET;
+ dev->event_types = type3_events;
goto out;
}
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
if (pcidev) {
- dev->control = &spic_types[2];
+ dev->model = SONYPI_DEVICE_TYPE3;
+ dev->handle_irq = type3_handle_irq;
+ dev->evport_offset = SONYPI_TYPE3_OFFSET;
+ dev->event_types = type3_events;
goto out;
}
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
if (pcidev) {
- dev->control = &spic_types[2];
+ dev->model = SONYPI_DEVICE_TYPE3;
+ dev->handle_irq = type3_handle_irq;
+ dev->evport_offset = SONYPI_TYPE3_OFFSET;
+ dev->event_types = type3_events;
goto out;
}
/* default */
- dev->control = &spic_types[1];
+ dev->model = SONYPI_DEVICE_TYPE2;
+ dev->evport_offset = SONYPI_TYPE2_OFFSET;
+ dev->event_types = type2_events;
out:
if (pcidev)
pci_dev_put(pcidev);
printk(KERN_INFO DRV_PFX "detected Type%d model\n",
- dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
- dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
+ dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
+ dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
}
/* camera tests and poweron/poweroff */
@@ -2099,7 +2127,7 @@ static struct attribute_group spic_attribute_group = {
struct sonypi_compat_s {
struct fasync_struct *fifo_async;
- struct kfifo *fifo;
+ struct kfifo fifo;
spinlock_t fifo_lock;
wait_queue_head_t fifo_proc_list;
atomic_t open_count;
@@ -2124,12 +2152,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file)
/* Flush input queue on first open */
unsigned long flags;
- spin_lock_irqsave(sonypi_compat.fifo->lock, flags);
+ spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
if (atomic_inc_return(&sonypi_compat.open_count) == 1)
- __kfifo_reset(sonypi_compat.fifo);
+ kfifo_reset(&sonypi_compat.fifo);
- spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags);
+ spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
return 0;
}
@@ -2140,17 +2168,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
ssize_t ret;
unsigned char c;
- if ((kfifo_len(sonypi_compat.fifo) == 0) &&
+ if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
- kfifo_len(sonypi_compat.fifo) != 0);
+ kfifo_len(&sonypi_compat.fifo) != 0);
if (ret)
return ret;
while (ret < count &&
- (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
+ (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
+ &sonypi_compat.fifo_lock) == sizeof(c))) {
if (put_user(c, buf++))
return -EFAULT;
ret++;
@@ -2167,7 +2196,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
- if (kfifo_len(sonypi_compat.fifo))
+ if (kfifo_len(&sonypi_compat.fifo))
return POLLIN | POLLRDNORM;
return 0;
}
@@ -2329,7 +2358,8 @@ static struct miscdevice sonypi_misc_device = {
static void sonypi_compat_report_event(u8 event)
{
- kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
+ kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
+ sizeof(event), &sonypi_compat.fifo_lock);
kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
wake_up_interruptible(&sonypi_compat.fifo_proc_list);
}
@@ -2339,11 +2369,11 @@ static int sonypi_compat_init(void)
int error;
spin_lock_init(&sonypi_compat.fifo_lock);
- sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
- &sonypi_compat.fifo_lock);
- if (IS_ERR(sonypi_compat.fifo)) {
+ error =
+ kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+ if (error) {
printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
- return PTR_ERR(sonypi_compat.fifo);
+ return error;
}
init_waitqueue_head(&sonypi_compat.fifo_proc_list);
@@ -2362,14 +2392,14 @@ static int sonypi_compat_init(void)
return 0;
err_free_kfifo:
- kfifo_free(sonypi_compat.fifo);
+ kfifo_free(&sonypi_compat.fifo);
return error;
}
static void sonypi_compat_exit(void)
{
misc_deregister(&sonypi_misc_device);
- kfifo_free(sonypi_compat.fifo);
+ kfifo_free(&sonypi_compat.fifo);
}
#else
static int sonypi_compat_init(void) { return 0; }
@@ -2566,7 +2596,7 @@ static int sony_pic_enable(struct acpi_device *device,
buffer.pointer = resource;
/* setup Type 1 resources */
- if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) {
+ if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
/* setup io resources */
resource->res1.type = ACPI_RESOURCE_TYPE_IO;
@@ -2649,29 +2679,28 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
data_mask = inb_p(dev->cur_ioport->io2.minimum);
else
data_mask = inb_p(dev->cur_ioport->io1.minimum +
- dev->control->evport_offset);
+ dev->evport_offset);
dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
ev, data_mask, dev->cur_ioport->io1.minimum,
- dev->control->evport_offset);
+ dev->evport_offset);
if (ev == 0x00 || ev == 0xff)
return IRQ_HANDLED;
- for (i = 0; dev->control->event_types[i].mask; i++) {
+ for (i = 0; dev->event_types[i].mask; i++) {
- if ((data_mask & dev->control->event_types[i].data) !=
- dev->control->event_types[i].data)
+ if ((data_mask & dev->event_types[i].data) !=
+ dev->event_types[i].data)
continue;
- if (!(mask & dev->control->event_types[i].mask))
+ if (!(mask & dev->event_types[i].mask))
continue;
- for (j = 0; dev->control->event_types[i].events[j].event; j++) {
- if (ev == dev->control->event_types[i].events[j].data) {
+ for (j = 0; dev->event_types[i].events[j].event; j++) {
+ if (ev == dev->event_types[i].events[j].data) {
device_event =
- dev->control->
- event_types[i].events[j].event;
+ dev->event_types[i].events[j].event;
goto found;
}
}
@@ -2679,13 +2708,12 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
/* Still not able to decode the event try to pass
* it over to the minidriver
*/
- if (dev->control->handle_irq &&
- dev->control->handle_irq(data_mask, ev) == 0)
+ if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
return IRQ_HANDLED;
dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
ev, data_mask, dev->cur_ioport->io1.minimum,
- dev->control->evport_offset);
+ dev->evport_offset);
return IRQ_HANDLED;
found:
@@ -2816,7 +2844,7 @@ static int sony_pic_add(struct acpi_device *device)
/* request IRQ */
list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
- IRQF_SHARED, "sony-laptop", &spic_dev)) {
+ IRQF_DISABLED, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
"polarity: %d - shr: %d\n",
irq->irq.interrupts[0],
@@ -2949,6 +2977,7 @@ static int __init sony_laptop_init(void)
"Unable to register SPIC driver.");
goto out;
}
+ spic_drv_registered = 1;
}
result = acpi_bus_register_driver(&sony_nc_driver);
@@ -2960,7 +2989,7 @@ static int __init sony_laptop_init(void)
return 0;
out_unregister_pic:
- if (!no_spic)
+ if (spic_drv_registered)
acpi_bus_unregister_driver(&sony_pic_driver);
out:
return result;
@@ -2969,7 +2998,7 @@ out:
static void __exit sony_laptop_exit(void)
{
acpi_bus_unregister_driver(&sony_nc_driver);
- if (!no_spic)
+ if (spic_drv_registered)
acpi_bus_unregister_driver(&sony_pic_driver);
}