From 827b4649d4626bf97b203b4bcd69476bb9b4e760 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 29 Sep 2009 00:10:41 +0200 Subject: PM / PCMCIA: Drop second argument of pcmcia_socket_dev_suspend() pcmcia_socket_dev_suspend() doesn't use its second argument, so it may be dropped safely. This change is necessary for the subsequent yenta suspend/resume fix. Signed-off-by: Rafael J. Wysocki Cc: stable@kernel.org diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 9e1140f..e1dcced 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -363,7 +363,7 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg) struct at91_cf_socket *cf = platform_get_drvdata(pdev); struct at91_cf_data *board = cf->board; - pcmcia_socket_dev_suspend(&pdev->dev, mesg); + pcmcia_socket_dev_suspend(&pdev->dev); if (device_may_wakeup(&pdev->dev)) { enable_irq_wake(board->det_pin); if (board->irq_pin) diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 9001334..0208870 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -515,7 +515,7 @@ static int au1x00_drv_pcmcia_probe(struct platform_device *dev) static int au1x00_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int au1x00_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index b59d411..300b368 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c @@ -302,7 +302,7 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev) static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg) { - return pcmcia_socket_dev_suspend(&pdev->dev, mesg); + return pcmcia_socket_dev_suspend(&pdev->dev); } static int bfin_cf_resume(struct platform_device *pdev) diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 0660ad1..934d4be 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -101,7 +101,7 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem); static int socket_resume(struct pcmcia_socket *skt); static int socket_suspend(struct pcmcia_socket *skt); -int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state) +int pcmcia_socket_dev_suspend(struct device *dev) { struct pcmcia_socket *socket; diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 46561fa..a04f21c 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); #ifdef CONFIG_PM static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int i82092aa_socket_resume (struct pci_dev *dev) diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 40d4953..b906abe 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1241,7 +1241,7 @@ static int pcic_init(struct pcmcia_socket *s) static int i82365_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int i82365_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 62b4ecc..d1d89c4 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -699,7 +699,7 @@ static struct pccard_operations pcc_operations = { static int cfc_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int cfc_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 12034b4..a065583 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -675,7 +675,7 @@ static struct pccard_operations pcc_operations = { static int pcc_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int pcc_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index d1ad096..c69f2c4 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -1296,7 +1296,7 @@ static int m8xx_remove(struct of_device *ofdev) #ifdef CONFIG_PM static int m8xx_suspend(struct platform_device *pdev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&pdev->dev, state); + return pcmcia_socket_dev_suspend(&pdev->dev); } static int m8xx_resume(struct platform_device *pdev) diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index f373639..68570bc 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -334,7 +334,7 @@ static int __exit omap_cf_remove(struct platform_device *pdev) static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg) { - return pcmcia_socket_dev_suspend(&pdev->dev, mesg); + return pcmcia_socket_dev_suspend(&pdev->dev); } static int omap_cf_resume(struct platform_device *pdev) diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 8bed1da..1c39d34 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -758,7 +758,7 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev) #ifdef CONFIG_PM static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int pd6729_socket_resume(struct pci_dev *dev) diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 87e22ef..0e35acb 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -302,7 +302,7 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) static int pxa2xx_drv_pcmcia_suspend(struct device *dev) { - return pcmcia_socket_dev_suspend(dev, PMSG_SUSPEND); + return pcmcia_socket_dev_suspend(dev); } static int pxa2xx_drv_pcmcia_resume(struct device *dev) diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index d8da5ac..2d0e997 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -89,7 +89,7 @@ static int sa11x0_drv_pcmcia_remove(struct platform_device *dev) static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int sa11x0_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 401052a2..4be4e17 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -159,7 +159,7 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev) static int pcmcia_suspend(struct sa1111_dev *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int pcmcia_resume(struct sa1111_dev *dev) diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 8eb0423..582413f 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -366,7 +366,7 @@ static int __init get_tcic_id(void) static int tcic_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int tcic_drv_pcmcia_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index d4ad50d..c9fcbdc 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -707,7 +707,7 @@ __setup("vrc4171_card=", vrc4171_card_setup); static int vrc4171_card_suspend(struct platform_device *dev, pm_message_t state) { - return pcmcia_socket_dev_suspend(&dev->dev, state); + return pcmcia_socket_dev_suspend(&dev->dev); } static int vrc4171_card_resume(struct platform_device *dev) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index b459e87..6fa1ed8 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1230,7 +1230,7 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) struct yenta_socket *socket = pci_get_drvdata(dev); int ret; - ret = pcmcia_socket_dev_suspend(&dev->dev, state); + ret = pcmcia_socket_dev_suspend(&dev->dev); if (socket) { if (socket->type && socket->type->save_state) diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 9a3b498..d696a69 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -279,7 +279,7 @@ extern struct pccard_resource_ops pccard_iodyn_ops; extern struct pccard_resource_ops pccard_nonstatic_ops; /* socket drivers are expected to use these callbacks in their .drv struct */ -extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state); +extern int pcmcia_socket_dev_suspend(struct device *dev); extern int pcmcia_socket_dev_resume(struct device *dev); /* socket drivers use this callback in their IRQ handler */ -- cgit v0.10.2 From 0c570cdeb8fdfcb354a3e9cd81bfc6a09c19de0c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 29 Sep 2009 00:11:03 +0200 Subject: PM / yenta: Fix cardbus suspend/resume regression Since 2.6.29 the PCI PM core have been restoring the standard configuration registers of PCI devices in the early phase of resume. In particular, PCI devices without drivers have been handled this way since commit 355a72d75b3b4f4877db4c9070c798238028ecb5 (PCI: Rework default handling of suspend and resume). Unfortunately, this leads to post-resume problems with CardBus devices which cannot be accessed in the early phase of resume, because the sockets they are on have not been woken up yet at that point. To solve this problem, move the yenta socket resume to the early phase of resume and, analogously, move the suspend of it to the late phase of suspend. Additionally, remove some unnecessary PCI code from the yenta socket's resume routine. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13092, which is a post-2.6.28 regression. Signed-off-by: Rafael J. Wysocki Reported-by: Florian Cc: stable@kernel.org diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 6fa1ed8..abe0e44 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1225,60 +1225,71 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i } #ifdef CONFIG_PM -static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) +static int yenta_dev_suspend_noirq(struct device *dev) { - struct yenta_socket *socket = pci_get_drvdata(dev); + struct pci_dev *pdev = to_pci_dev(dev); + struct yenta_socket *socket = pci_get_drvdata(pdev); int ret; - ret = pcmcia_socket_dev_suspend(&dev->dev); + ret = pcmcia_socket_dev_suspend(dev); - if (socket) { - if (socket->type && socket->type->save_state) - socket->type->save_state(socket); + if (!socket) + return ret; - /* FIXME: pci_save_state needs to have a better interface */ - pci_save_state(dev); - pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); - pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); - pci_disable_device(dev); + if (socket->type && socket->type->save_state) + socket->type->save_state(socket); - /* - * Some laptops (IBM T22) do not like us putting the Cardbus - * bridge into D3. At a guess, some other laptop will - * probably require this, so leave it commented out for now. - */ - /* pci_set_power_state(dev, 3); */ - } + pci_save_state(pdev); + pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]); + pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); + pci_disable_device(pdev); + + /* + * Some laptops (IBM T22) do not like us putting the Cardbus + * bridge into D3. At a guess, some other laptop will + * probably require this, so leave it commented out for now. + */ + /* pci_set_power_state(dev, 3); */ return ret; } - -static int yenta_dev_resume (struct pci_dev *dev) +static int yenta_dev_resume_noirq(struct device *dev) { - struct yenta_socket *socket = pci_get_drvdata(dev); + struct pci_dev *pdev = to_pci_dev(dev); + struct yenta_socket *socket = pci_get_drvdata(pdev); + int ret; - if (socket) { - int rc; + if (!socket) + return 0; - pci_set_power_state(dev, 0); - /* FIXME: pci_restore_state needs to have a better interface */ - pci_restore_state(dev); - pci_write_config_dword(dev, 16*4, socket->saved_state[0]); - pci_write_config_dword(dev, 17*4, socket->saved_state[1]); + pci_write_config_dword(pdev, 16*4, socket->saved_state[0]); + pci_write_config_dword(pdev, 17*4, socket->saved_state[1]); - rc = pci_enable_device(dev); - if (rc) - return rc; + ret = pci_enable_device(pdev); + if (ret) + return ret; - pci_set_master(dev); + pci_set_master(pdev); - if (socket->type && socket->type->restore_state) - socket->type->restore_state(socket); - } + if (socket->type && socket->type->restore_state) + socket->type->restore_state(socket); - return pcmcia_socket_dev_resume(&dev->dev); + return pcmcia_socket_dev_resume(dev); } + +static struct dev_pm_ops yenta_pm_ops = { + .suspend_noirq = yenta_dev_suspend_noirq, + .resume_noirq = yenta_dev_resume_noirq, + .freeze_noirq = yenta_dev_suspend_noirq, + .thaw_noirq = yenta_dev_resume_noirq, + .poweroff_noirq = yenta_dev_suspend_noirq, + .restore_noirq = yenta_dev_resume_noirq, +}; + +#define YENTA_PM_OPS (¥ta_pm_ops) +#else +#define YENTA_PM_OPS NULL #endif #define CB_ID(vend,dev,type) \ @@ -1376,10 +1387,7 @@ static struct pci_driver yenta_cardbus_driver = { .id_table = yenta_table, .probe = yenta_probe, .remove = __devexit_p(yenta_close), -#ifdef CONFIG_PM - .suspend = yenta_dev_suspend, - .resume = yenta_dev_resume, -#endif + .driver.pm = YENTA_PM_OPS, }; -- cgit v0.10.2