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

[PATCH] sonypi: power management related fixes

 * switch from a sysdev to a platform device
 * drop old style PM code
 * use pci_get_device()/pci_dev_put() instead of pci_find_device()

Patch originaly from Dmitry Torokhov <dtor@mail.ru>.
Signed-off-by: default avatarStelian Pop <stelian@popies.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d3d03018
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/sysdev.h> #include <linux/err.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -608,81 +608,91 @@ struct miscdevice sonypi_misc_device = { ...@@ -608,81 +608,91 @@ struct miscdevice sonypi_misc_device = {
-1, "sonypi", &sonypi_misc_fops -1, "sonypi", &sonypi_misc_fops
}; };
#ifdef CONFIG_PM static void sonypi_enable(unsigned int camera_on)
static int old_camera_power; {
static int sonypi_suspend(struct sys_device *dev, u32 state) {
sonypi_call2(0x81, 0); /* make sure we don't get any more events */
if (camera) {
old_camera_power = sonypi_device.camera_power;
sonypi_camera_off();
}
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_dis(); sonypi_type2_srs();
else else
sonypi_type1_dis(); sonypi_type1_srs();
/* disable ACPI mode */
if (!SONYPI_ACPI_ACTIVE && fnkeyinit) sonypi_call1(0x82);
outb(0xf1, 0xb2); sonypi_call2(0x81, 0xff);
return 0; sonypi_call1(compat ? 0x92 : 0x82);
}
static int sonypi_resume(struct sys_device *dev) {
/* Enable ACPI mode to get Fn key events */ /* Enable ACPI mode to get Fn key events */
if (!SONYPI_ACPI_ACTIVE && fnkeyinit) if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf0, 0xb2); outb(0xf0, 0xb2);
if (camera && camera_on)
sonypi_camera_on();
}
static int sonypi_disable(void)
{
sonypi_call2(0x81, 0); /* make sure we don't get any more events */
if (camera)
sonypi_camera_off();
/* disable ACPI mode */
if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf1, 0xb2);
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_srs(); sonypi_type2_dis();
else
sonypi_type1_srs();
sonypi_call1(0x82);
sonypi_call2(0x81, 0xff);
if (compat)
sonypi_call1(0x92);
else else
sonypi_call1(0x82); sonypi_type1_dis();
if (camera && old_camera_power)
sonypi_camera_on();
return 0; return 0;
} }
/* Old PM scheme */ #ifdef CONFIG_PM
static int sonypi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) { static int old_camera_power;
switch (rqst) { static int sonypi_suspend(struct device *dev, u32 state, u32 level)
case PM_SUSPEND: {
sonypi_suspend(NULL, 0); if (level == SUSPEND_DISABLE) {
break; old_camera_power = sonypi_device.camera_power;
case PM_RESUME: sonypi_disable();
sonypi_resume(NULL);
break;
} }
return 0; return 0;
} }
/* New PM scheme (device model) */ static int sonypi_resume(struct device *dev, u32 level)
static struct sysdev_class sonypi_sysclass = { {
set_kset_name("sonypi"), if (level == RESUME_ENABLE)
.suspend = sonypi_suspend, sonypi_enable(old_camera_power);
.resume = sonypi_resume, return 0;
}; }
#endif
static struct sys_device sonypi_sysdev = { static void sonypi_shutdown(struct device *dev)
.id = 0, {
.cls = &sonypi_sysclass, sonypi_disable();
}; }
static struct device_driver sonypi_driver = {
.name = "sonypi",
.bus = &platform_bus_type,
#ifdef CONFIG_PM
.suspend = sonypi_suspend,
.resume = sonypi_resume,
#endif #endif
.shutdown = sonypi_shutdown,
};
static int __devinit sonypi_probe(struct pci_dev *pcidev) { static int __devinit sonypi_probe(void)
{
int i, ret; int i, ret;
struct sonypi_ioport_list *ioport_list; struct sonypi_ioport_list *ioport_list;
struct sonypi_irq_list *irq_list; struct sonypi_irq_list *irq_list;
struct pci_dev *pcidev;
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
sonypi_device.dev = pcidev; sonypi_device.dev = pcidev;
if (pcidev) sonypi_device.model = pcidev ?
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2;
else
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
sonypi_device.fifo_lock = SPIN_LOCK_UNLOCKED; sonypi_device.fifo_lock = SPIN_LOCK_UNLOCKED;
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock); &sonypi_device.fifo_lock);
...@@ -743,29 +753,9 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -743,29 +753,9 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
sonypi_device.irq = irq_list[i].irq; sonypi_device.irq = irq_list[i].irq;
sonypi_device.bits = irq_list[i].bits; sonypi_device.bits = irq_list[i].bits;
/* Enable sonypi IRQ settings */ if (!request_irq(sonypi_device.irq, sonypi_irq,
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_srs();
else
sonypi_type1_srs();
sonypi_call1(0x82);
sonypi_call2(0x81, 0xff);
if (compat)
sonypi_call1(0x92);
else
sonypi_call1(0x82);
/* Now try requesting the irq from the system */
if (!request_irq(sonypi_device.irq, sonypi_irq,
SA_SHIRQ, "sonypi", sonypi_irq)) SA_SHIRQ, "sonypi", sonypi_irq))
break; break;
/* If request_irq failed, disable sonypi IRQ settings */
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_dis();
else
sonypi_type1_dis();
} }
if (!irq_list[i].irq) { if (!irq_list[i].irq) {
...@@ -774,24 +764,14 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -774,24 +764,14 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
goto out3; goto out3;
} }
#ifdef CONFIG_PM sonypi_device.pdev = platform_device_register_simple("sonypi", -1,
sonypi_device.pm = pm_register(PM_PCI_DEV, 0, sonypi_pm_callback); NULL, 0);
if (IS_ERR(sonypi_device.pdev)) {
if (sysdev_class_register(&sonypi_sysclass) != 0) { ret = PTR_ERR(sonypi_device.pdev);
printk(KERN_ERR "sonypi: sysdev_class_register failed\n"); goto out_platformdev;
ret = -ENODEV;
goto out4;
}
if (sysdev_register(&sonypi_sysdev) != 0) {
printk(KERN_ERR "sonypi: sysdev_register failed\n");
ret = -ENODEV;
goto out5;
} }
#endif
/* Enable ACPI mode to get Fn key events */ sonypi_enable(0);
if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf0, 0xb2);
printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%s.\n", printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%s.\n",
SONYPI_DRIVER_VERSION); SONYPI_DRIVER_VERSION);
...@@ -834,12 +814,7 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -834,12 +814,7 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
return 0; return 0;
#ifdef CONFIG_PM out_platformdev:
out5:
sysdev_class_unregister(&sonypi_sysclass);
out4:
free_irq(sonypi_device.irq, sonypi_irq);
#endif
out3: out3:
release_region(sonypi_device.ioport1, sonypi_device.region_size); release_region(sonypi_device.ioport1, sonypi_device.region_size);
out2: out2:
...@@ -847,20 +822,16 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { ...@@ -847,20 +822,16 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
out1: out1:
kfifo_free(sonypi_device.fifo); kfifo_free(sonypi_device.fifo);
out_fifo: out_fifo:
pci_dev_put(sonypi_device.dev);
return ret; return ret;
} }
static void __devexit sonypi_remove(void) { static void __devexit sonypi_remove(void)
{
#ifdef CONFIG_PM sonypi_disable();
pm_unregister(sonypi_device.pm);
sysdev_unregister(&sonypi_sysdev); platform_device_unregister(sonypi_device.pdev);
sysdev_class_unregister(&sonypi_sysclass);
#endif
sonypi_call2(0x81, 0); /* make sure we don't get any more events */
#ifdef SONYPI_USE_INPUT #ifdef SONYPI_USE_INPUT
if (useinput) { if (useinput) {
input_unregister_device(&sonypi_device.jog_dev); input_unregister_device(&sonypi_device.jog_dev);
...@@ -868,19 +839,13 @@ static void __devexit sonypi_remove(void) { ...@@ -868,19 +839,13 @@ static void __devexit sonypi_remove(void) {
} }
#endif /* SONYPI_USE_INPUT */ #endif /* SONYPI_USE_INPUT */
if (camera)
sonypi_camera_off();
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_dis();
else
sonypi_type1_dis();
/* disable ACPI mode */
if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf1, 0xb2);
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);
if (sonypi_device.dev)
pci_disable_device(sonypi_device.dev);
kfifo_free(sonypi_device.fifo); kfifo_free(sonypi_device.fifo);
pci_dev_put(sonypi_device.dev);
printk(KERN_INFO "sonypi: removed.\n"); printk(KERN_INFO "sonypi: removed.\n");
} }
...@@ -904,18 +869,25 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { ...@@ -904,18 +869,25 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = {
static int __init sonypi_init(void) static int __init sonypi_init(void)
{ {
struct pci_dev *pcidev = NULL; int ret;
if (dmi_check_system(sonypi_dmi_table)) {
pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, if (!dmi_check_system(sonypi_dmi_table))
PCI_DEVICE_ID_INTEL_82371AB_3,
NULL);
return sonypi_probe(pcidev);
}
else
return -ENODEV; return -ENODEV;
ret = driver_register(&sonypi_driver);
if (ret)
return ret;
ret = sonypi_probe();
if (ret)
driver_unregister(&sonypi_driver);
return ret;
} }
static void __exit sonypi_exit(void) { static void __exit sonypi_exit(void)
{
driver_unregister(&sonypi_driver);
sonypi_remove(); sonypi_remove();
} }
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/pm.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/sonypi.h> #include <linux/sonypi.h>
...@@ -355,6 +354,7 @@ struct sonypi_eventtypes { ...@@ -355,6 +354,7 @@ struct sonypi_eventtypes {
struct sonypi_device { struct sonypi_device {
struct pci_dev *dev; struct pci_dev *dev;
struct platform_device *pdev;
u16 irq; u16 irq;
u16 bits; u16 bits;
u16 ioport1; u16 ioport1;
...@@ -373,9 +373,6 @@ struct sonypi_device { ...@@ -373,9 +373,6 @@ struct sonypi_device {
#ifdef SONYPI_USE_INPUT #ifdef SONYPI_USE_INPUT
struct input_dev jog_dev; struct input_dev jog_dev;
#endif #endif
#ifdef CONFIG_PM
struct pm_dev *pm;
#endif
}; };
#define ITERATIONS_LONG 10000 #define ITERATIONS_LONG 10000
......
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